为什么我不能像C中的指针一样处理数组?

我在SO上看到了很多这个问题。 也许没有那么多的话……但是一次又一次地存在关于数组如何与指针不同的混淆。 所以我想我会花一点时间来问这个问题。

出于本Q&A的目的,我们将假设一个32位系统,并且已声明以下内容:

char * ptr = "hello"; char arr[10] = "hello"; int iarr[10] = {0}; 

这是一个问题列表,可以推测我在SO上看到的混乱。 当我看到新的问题时,我会添加到我的问答清单中(其他人也可以随意使用,如果您发现任何错误,请纠正我!)

  1. 指针和数组不是基本相同的东西吗?
  2. 跟进: *(ptr)*(arr) ,或ptr[0]arr[0]给出相同的东西,为什么?
  3. 为什么arr&arr的价值相同?
  4. 跟进:为什么我得到一个不同的值打印arr+1 vs &arr+1

1) 指针不是数组。 数组不是指针。 不要那么想它们,因为它们是不同的。
我怎么能certificate这一点? 想想他们在记忆中的样子:

我们的数组arr长10个字符。 它包含“你好”,但等等,这不是全部! 因为我们有一个静态声明的数组比我们的消息长,所以我们得到一堆空字符( '\0' )免费提供! 另外,请注意名称arr在概念上如何附加到连续字符(它不指向任何东西)。 在此处输入图像描述

接下来考虑我们的指针在内存中的外观: 在此处输入图像描述 请注意,我们指向只读内存中某个位置的字符数组。

因此,虽然arrptr都以相同的方式初始化,但每个的内容/位置实际上是不同的。

这是关键点:
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”也会给出不同的结果。