我在SO上看到了很多这个问题。也许没有那么多的话......但是一次又一次地存在关于数组如何与指针不同的混淆。所以我想我会花点时间向Q& A谈几点。
出于本Q& A的目的,我们将假设一个32位系统,并宣布以下内容:
char * ptr = "hello";
char arr[10] = "hello";
int iarr[10] = {0};
这是一个问题列表,可以推测我在SO上看到的混乱。当我看到新的时候,我会添加到我的Q& A列表中(其他人也可以随意,如果你发现任何错误,请纠正我!)
*(ptr)
和*(arr)
,或ptr[0]
和arr[0]
都提供相同的内容,为什么?arr
和&arr
的值相同?arr+1
与&arr+1
不同的值?答案 0 :(得分:19)
1)指针不是数组。数组不是指针。不要那么想,因为它们是不同的 我该如何证明这一点?想一想他们在记忆中的样子:
我们的数组arr
长度为10个字符。它包含“你好”,但等等,这不是全部!因为我们有一个静态声明的数组比我们的消息长,所以我们得到一堆空字符('\0'
)免费提供!另外,请注意名称arr
在概念上如何附加到连续字符(它不指向任何内容)。
接下来考虑我们的指针在内存中的外观:
请注意,我们指向只读内存中某个位置的字符数组。
因此,虽然arr
和ptr
都以相同的方式初始化,但每个的内容/位置实际上是不同的。
这是关键点:
ptr 是一个变量,我们可以将它指向任何东西, arr 是一个常数,它总是指这个10个字符的块。
2)[]
是一个可以在地址上使用的“添加和参考”运算符。这意味着arr[0]
与*(arr+0)
相同。所以是的,这样做:
printf("%c %c", *(arr+1), *(ptr+1));
会给你输出“e e”。这不是因为数组是指针,而是因为数组arr
的名称和指针ptr
都恰好给你一个地址。
关键点#2: deference运算符*
和add和deference运算符[]
并不分别特定于指针和数组。这些操作员只需处理地址。
3)我没有一个非常简单的答案...所以让我们暂时忘记我们的字符数组,并看一下这个例子的解释:
int b; //this is integer type
&b; //this is the address of the int b, right?
int c[]; //this is the array of ints
&c; //this would be the address of the array, right?
所以这是可以理解的:
*c; //that's the first element in the array
这行代码告诉你什么?如果我尊重c
,那么我得到一个int。这意味着普通c
是一个地址。因为它是数组的开头,所以它是数组的地址,也是数组中第一个元素的地址,因此从价值的角度来看:
c == &c;
4)让我在这里讨论主题......这最后一个问题是地址算术混淆的一部分。我在SO上看到一个问题,暗示地址只是整数值...你需要明白在C地址中有类型的知识。也就是说:
iarr+1; //We added 1 to the address, so we moved 4 bytes
arr+1; //we added 1 to the address, so we moved 1 byte
基本上sizeof(int)
是4而sizeof(char)
是1.所以“向数组添加1”并不像看起来那么简单。
现在,回到问题,为什么arr+1
与&arr+1
不同?第一个是将1 * sizeof(char)
= 1添加到地址,第二个是将1 * sizeof(arr)
= 10添加到地址。
这就是为什么即使它们“只加1”也会给出不同的结果。