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

Mik*_*ike 6 c arrays pointers memory-address dereference

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

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

char * ptr = "hello";
char arr[10] = "hello";
int iarr[10] = {0};
Run Code Online (Sandbox Code Playgroud)

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

  1. 指针和数组不是基本相同的东西吗?
  2. 追问:既*(ptr)*(arr),或ptr[0]arr[0]给予同样的事情,为什么呢?
  3. 怎么来arr&arr同样的价值?
  4. 跟进:为什么我得到不同的打印值arr+1vs &arr+1

Mik*_*ike 19

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

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

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

因此,尽管双方arrptr进行初始化,以同样的方式,内容/每个位置实际上是不同的.

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


2)[]是一个可以在地址上使用的"添加和参考"运算符.含义arr[0]与说法相同*(arr+0).所以是的,这样做:

printf("%c %c", *(arr+1), *(ptr+1));
Run Code Online (Sandbox Code Playgroud)

会给你一个输出"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?
Run Code Online (Sandbox Code Playgroud)

所以这是可以理解的:

*c;   //that's the first element in the array
Run Code Online (Sandbox Code Playgroud)

这行代码告诉你什么?如果我尊重c,那么我得到一个int.这意味着普通c是一个地址.因为它是数组的开头,所以它是数组的地址,也是数组中第一个元素的地址,因此从价值的角度来看:

c == &c;
Run Code Online (Sandbox Code Playgroud)

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
Run Code Online (Sandbox Code Playgroud)

基本上sizeof(int)是4和sizeof(char)1.因此"向数组添加1"并不像它看起来那么简单.

那么现在,回到问题,为什么arr+1不同&arr+1?第一个是向1 * sizeof(char)地址添加= 1,第二个是向1 * sizeof(arr)地址添加= 10.

这就是为什么即使他们都"只加1"也会给出不同的结果.

  • @Mike:我不明白你为什么晚上提到_lvalue_。`arr` 和 `ptr` 都是左值,但每个表示变量或引用的标识符的表达式也是左值。它似乎与指针与数组的讨论无关。 (2认同)