2014-09-02 70 views
1

以下程序显示a和数组共享相同的地址。 我应该如何理解这种行为? 是否为& arr指针arr的地址,其中包含10个字符的开始地址?数组指针的地址,&array

#include <stdio.h> 

int main() 
{ 
    char arr[10] = {0}; 

    char* a = (char*)(&arr); 

    *a = 1; 

    printf("a=%p,arr=%p.\n", a, arr); 
    printf("%d\n", arr[0]); 
    return 0; 
} 
+0

'&arr'是'arr'的第一个元素的地址。当然,'a'具有相同的值,因为您首先为其分配了该值。 – 2014-09-02 14:59:37

+0

@亚历克斯:你必须学习的第一件事就是没有“指针'arr'”这样的东西。 'arr'数组是数组,而不是指针。那里没有任何指针。有大量的信息正确地解释了网络上的数组。 – AnT 2014-09-02 15:32:37

回答

2

当您分配C中的数组,什么你得到如下:

  +---+ 
    arr[0]: | | 
      +---+ 
    arr[1]: | | 
      +---+ 
      ... 
      +---+ 
arr[N-1]: | | 
      +---+ 

就是这样。没有为名为arr的对象留出单独的内存位置来存储数组第一个元素的地址。因此,阵列的第一个元素(&arr[0])的地址与数组本身的地址(&arr)是相同的

除了当它是sizeof或一元&运营商的操作数,或是一个字符串被用来在声明初始化另一个数组,类型“的T N元件阵列”的表达将被转换(“衰减”)转换为类型为“指向T的指针”的表达式,并且表达式的值将是该数组的第一个元素的地址。

因此,在第一个printf调用中的表达式arr的类型是char [10];根据上述规则,表达式“decays”键入char *,值为arr[0]的地址。

在表达式&arr中,arr是一元运算符&的操作数,所以不应用转换;代替获得char **类型的表达式,您会得到char (*)[10]类型的表达式(指向10个元素的数组char)。同样,由于阵列的第一个元素的地址与整个阵列的地址相同,因此表达式arr&arr具有相同的

0

通过arra打印出的地址是该阵列arr的第一个元素的存储器地址。 (请记住,数组的名称总是指向该数组的第一个元素的指针)。这是因为在定义了数组arr之后,您将a定义为指向内存中相同地址的指针。

1

在习惯C中,你应该写char *a = arr;char *a = &(arr[0]);&arr通常是char **。即使现代(C++)还是传统编译器自动,它是不正确的C.

作为arrchar阵列,arr[0]char和ARR是一样的&(arr[0])所以它是一个char *。如果你习惯于其他语言,这可能很奇怪,但它是如何工作的。如果arr是包括struct在内的任何其他类型的数组,它将是相同的。

+0

'&arr'将是'char(*)[10]',这是一个指向10个'char'数组的指针。 @FrédéricHamidi – alk 2014-09-02 16:21:52

+1

@FrédéricHamidi你可能会相信你想要的东西,但真正重要的是编译器会相信什么:-),我已经编辑了我的帖子,以便更清楚。 – 2014-09-02 17:11:08

0

按照C标准(6.3.2.1左值,数组和功能指示器)

3除了当它是sizeof操作或一元& 操作者的操作数,或是一个字符串文字用于初始化一个数组,一个 具有类型为'''的数组的表达式被转换为 表达式,其类型为指向类型''的指针,该指针指向数组对象的初始 元素,并且不是左值。如果数组对象 具有寄存器存储类,则行为未定义。

数组的地址是其第一个元素的地址。所以,虽然这些类型不同

char (*)[10](即对应于& ARR)和char *(也就是在铸造用在声明 的char * A =(字符*)(& ARR);),他们将具有相同的值那就是数组的第一个元素的地址。

如果你不会用铸件然后通过表达初始化的指针的正确定义& ARR将

char (*a)[10] = &arr; 

的差异被认为是把指针递增。为了定义指针a,表达式++a的值将比初​​始值大sizeof(char)。对于指针来说,表达式++的值比初始值大10 * sizeof(char)

在你的情况表达*a的类型是char,你可以写*a = 1;,而在我的情况下表达*a的类型将是char[10],你可以不写*a = 1;