2010-08-21 100 views
4

GCC 4.4.4的C89分配一个指向指针的数组为char

#define SIZE 5 
    char *names[SIZE] = {"peter", "lisa", "simon", "sarah", "julie"}; 
    char *search_names[SIZE] = {0}; 
    size_t i = 0; 

    for(i = 0; i < SIZE; i++) { 
     search_names[i] = names[i]++; 
    } 

    for(i = 0; i < SIZE; i++) { 
     printf("name to search for [ %s ]\n", search_names[i]); 
    } 

我感到困惑的这一行search_names[i] = names[i]++;这是一个指针数组为char *。只是我的实验,我认为它应该是&names[i]++。因为我想要在那个位置获得指针。因此,让&可以获得指针指向的地址。

我想我可以像这样增加:(names[i]) + i;

只是对这条线感到困惑。

+1

我不认为我完全理解你的代码的意图。这两个数组都是指向char的指针数组。你只是将一个数组复制到另一个数组中?在这种情况下,它应该是“search_names [i] = names [i];”。为什么你需要增加? – 2010-08-21 19:04:50

+1

是的,你是对的。我只是试验和尝试不同的事情。但是,search_names [i] = names [i];产生与search_names [i] = names [i] ++相同的结果;这是否意味着它们在某种意义上是平等的。名称[i] ++会增加多少?谢谢。 – ant2009 2010-08-21 19:13:40

+2

名称[i]是指像“彼得”这样的字符串。在C中,字符串被存储为字符数组,以“\ 0”结尾。当你抓住名字[i]时,你实际上是抓住一个指向名字[i]的字符串中的第一个元素的指针,换句话说,在“peter \ 0”中指向“p”的指针。当你增加指针时,它向前移动一个空格,指向“e”,使“eter \ 0”。尽管由于模糊的优先规则,在赋值给search_names [i]之后增量发生,因此它看起来相同,但是您正在执行额外的指针操作。 – 2010-08-21 19:37:10

回答

7

names[i]是一个指针,类型为char*&names[i]是指向names[i]的指针,因此具有类型char**。一些存储器的图片:

names     for each i, this is where names[i] *points* 
|__________________   0  1 2  3  4 
|     |   |  | |  |  | 
|     |   v  v v  v  v 
[0 ][1 ][2 ][3 ][4 ] <gap> peter0lisa0simon0sarah0julie0 
     ^
     |_This is where &names[2] points, i.e. this is where names[2] *is* 

name是5个指针数组,我已经描绘为具有方括号和它的索引每个指针。再加上一个空格,因为指针在我的机器上是4个字节。这是names刚刚初始化后的情况。右边的单独内存块是一个字节序列,每个0表示一个0/NUL字节,而不是字符0。这是实现的责任(编译器,链接器和加载器一起工作)为字符串文字分配内存 - 我假设你已经使用的所有字符串文字将被聚集在一起,尽管情况并非如此。最后,数字0 ... 4指示names中的每个指针指向的位置。

由于您正在分配到char*,因此您需要一个char*。或者以另一种方式来看,指针指向相同的事物,如果(且仅当)指针本身具有相同的值。所以如果你想search_names[i](这是一个指针)指向names[i]指向的相同的东西,那么search_names[i] = names[i]是完全正确的。

虽然我不知道做什么的目的是names[i]++。它修改指针names[i]。修改指针可以指向不同的事物。在这种情况下,您将以names[0]指向“eter”,names[1]指向“isa”,依此类推。

这里是内存看起来像你递增每个指针在names后:

names     
|_____________   0  1 2  3  4 
|    |   |  | |  |  | 
v    v   v  v v  v  v 
[0][1][2][3][4]   peter0lisa0simon0sarah0julie0 

顺便说一句,你允许到一个字符串赋值给char*,但是,这并不意味着你应该。宣布你的阵列const char *names[SIZE]会更好。修改编译器为字符串文字分配的内存是未定义的行为,并且使用const char*而不是char*可以帮助执行该操作。

+0

很好的解释。谢谢。 – ant2009 2010-08-22 02:13:10

2

名称[]被定义为指向字符的指针数组。因此,名称[i]是指向名称中包含的第i个字符串的指针。 search_names []是指向char的指针数组,因此search_names [i]也是一个指针。因此,不需要将地址运算符应用于名称[i]以使search_names [i]指向与名称[i]相同的字符串。希望能够为你澄清事情。

1

所以你试图将数组名称复制到search_names?请注意,名称和search_names都是指向字符的指针。 IE,名称[i]是一个指针。

表达

search_names[i] = names[i] 

分配search_names的值[I]是名称[i]中。这只是将地址&运行时栈上的内容放入地址为& search_names [i]的单元中。在这种情况下,它只是复制一个指针。它不会复制字符。它只会复制单元格名称[i]中的内容 - 指向字符序列第一个字符的指针。

之所以

search_names[i] = names[i]++; 

相当于

search_names[i] = names[i] 

在search_names的背景是因为增量操作影响名称[I]的值。它在赋值运算符后的优先级较低。所以表达式会在赋值之后递增名称[i]。由于names [i]是一个指针,因此增量会执行一些指针算术,这意味着它将指向address(names [i] + sizeof(char))。

相关问题