为什么我不能像C中的指针一样处理数组?
我在SO上看到了很多这个问题。 也许没有那么多的话……但是一次又一次地存在关于数组如何与指针不同的混淆。 所以我想我会花一点时间来问这个问题。
出于本Q&A的目的,我们将假设一个32位系统,并且已声明以下内容:
char * ptr = "hello"; char arr[10] = "hello"; int iarr[10] = {0};
这是一个问题列表,可以推测我在SO上看到的混乱。 当我看到新的问题时,我会添加到我的问答清单中(其他人也可以随意使用,如果您发现任何错误,请纠正我!)
- 指针和数组不是基本相同的东西吗?
- 跟进:
*(ptr)
和*(arr)
,或ptr[0]
和arr[0]
给出相同的东西,为什么? - 为什么
arr
和&arr
的价值相同? - 跟进:为什么我得到一个不同的值打印
arr+1
vs&arr+1
?
1) 指针不是数组。 数组不是指针。 不要那么想它们,因为它们是不同的。
我怎么能certificate这一点? 想想他们在记忆中的样子:
我们的数组arr
长10个字符。 它包含“你好”,但等等,这不是全部! 因为我们有一个静态声明的数组比我们的消息长,所以我们得到一堆空字符( '\0'
)免费提供! 另外,请注意名称arr
在概念上如何附加到连续字符(它不指向任何东西)。
接下来考虑我们的指针在内存中的外观: 请注意,我们指向只读内存中某个位置的字符数组。
因此,虽然arr
和ptr
都以相同的方式初始化,但每个的内容/位置实际上是不同的。
这是关键点:
ptr是一个变量,我们可以将它指向任何东西, arr是一个常量,它总是引用这个10个字符的块。
2) []
是一个可以在地址上使用的“加法和参考”运算符。 意思是arr[0]
与说*(arr+0)
。 所以是的,这样做:
printf("%c %c", *(arr+1), *(ptr+1));
会给你一个输出“ee”。 这不是因为数组是指针,而是因为数组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”也会给出不同的结果。