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上看到的困惑.当我看到新的问题时,我会添加到我的问答清单中(其他人也可以随意,如果你发现任何错误,请纠正我!)
*(ptr)和*(arr),或ptr[0]和arr[0]给予同样的事情,为什么呢?arr和&arr同样的价值?arr+1vs &arr+1?Mik*_*ike 19
1)指针不是数组.数组不是指针.不要那么想他们,因为他们是不同的.
我该如何证明这一点?想想他们在记忆中的样子:
我们的数组长arr10个字符.它包含"你好",但等等,这不是全部!因为我们有一个静态声明的数组比我们的消息更长,所以我们得到了一堆免费的NULL字符('\0')!另外,请注意名称arr在概念上如何附加到连续的字符(它不指向任何东西).

接下来考虑我们的指针在内存中的外观:
请注意,我们指向只读内存中某个位置的字符数组.
因此,尽管双方arr并ptr进行初始化,以同样的方式,内容/每个位置实际上是不同的.
这是关键点:
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"也会给出不同的结果.