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

时间:2012-10-01 15:35:11

标签: c arrays pointers dereference memory-address

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

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

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

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

  1. 指针和数组基本上不是一回事吗?
  2. 跟进:*(ptr)*(arr),或ptr[0]arr[0]都提供相同的内容,为什么?
  3. 为什么arr&arr的值相同?
  4. 跟进:为什么我会打印arr+1&arr+1不同的值?

1 个答案:

答案 0 :(得分:19)

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

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

接下来考虑我们的指针在内存中的外观: enter image description here 请注意,我们指向只读内存中某个位置的字符数组。

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

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