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*
有助于强制执行。