8

我在 SO 上经常看到这个问题。也许不是这么多话......但一次又一次地混淆了数组与指针的不同之处。所以我想我会花点时间来问答一些关于这个的问题。

出于本问答的目的,我们将假设一个 32 位系统,并声明了以下内容:

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

以下是我在 SO 上看到的困惑的问题列表。当我看到新的问题时,我会添加到我的问答列表中(其他人也可以随意添加,如果您发现任何错误,请纠正我!)

  1. 指针和数组基本上不是一回事吗?
  2. 跟进:*(ptr)and *(arr), or ptr[0]andarr[0]给出相同的东西,为什么?
  3. 怎么会arr&arr值一样?
  4. 跟进:为什么我得到不同的值打印arr+1&arr+1
4

1 回答 1

21

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

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

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

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

这是关键点:
ptr是一个变量,我们可以将它指向任何东西,arr是一个常量,它总是会引用这个 10 个字符的块。


2) The[]是可用于地址的“添加和引用”运算符。意思arr[0]和说的一样*(arr+0)。所以是的,这样做:

printf("%c %c", *(arr+1), *(ptr+1));

会给你一个“e e”的输出。这不是因为数组是指针,而是因为数组的名称arr和指针ptr都恰好给了你一个地址。

#2 的关键点:引用运算符*和加法和引用运算符[]并不分别特定于指针和数组。这些运算符只处理地址。


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”,它们也会给出不同的结果。

于 2012-10-01T15:35:10.843 回答