为什么数组的名称,数组的地址和数组的值都是一样的?

时间:2014-12-29 04:49:33

标签: c arrays memory-address

这是一个二维数组。据我所知,数组的名称指向数组中的第一个元素,即& array [0] [0]。但是当我尝试打印时,数组的名称,数组的地址和数组的值都是相同的。

#include <stdio.h>
int main(void)
{
    int array[4][2]={1,2,3,4,5,6,7,8};
    printf("%d    %d\n",
           &array[0][0], array[0][0]);
    printf("%d    %d    %d    %d\n",
           array, &array, *array, **array);
}

输出

2686704    1
2686704    2686704    2686704    1

4 个答案:

答案 0 :(得分:1)

在您的代码中(已更正):

#include <stdio.h>
int main(void)
{
    int array[4][2] = {1,2,3,4,5,6,7,8};
    printf("%p    %d\n",
           (void *) &array[0][0], array[0][0]);
    printf("%p    %p    %p    %d\n",
           (void *) array, (void *) &array, (void *) *array, **array);
}

在上次printf()电话中:

  • arrayint的二维数组,但在此上下文中,数组的名称衰减为指向其第一个元素的指针。它的第一个元素是array[0],而不是array[0][0],事实证明:

    int * p = array;
    

    应该给你一个警告,同时:

    int (*p)[2] = array;
    

    不应该。

    由于数组在内存中的布局方式,array的地址与array[0]的地址相同,array[0][0]的地址与{的地址相同{1}}。

  • &array是数组的地址,与第一个元素的地址相同......依此类推。

  • *array相当于array[0]array[0]的类型是int大小为2的数组。由于array[0]本身就是一个数组,它在这里也会衰变为指向其第一个元素的指针,正如所解释的那样是与&array相同的地址,并且同一地址array衰减到这里

  • **array相当于array[0][0],最后,它是一个实际的int,而不是一个数组,因此不会衰减到任何类型的地址,它只是值1

这就是前三个表达式都评估到同一地址的原因。

请注意,%p用于指针,并且因为printf()是一个可变参数函数,编译器不能像通常那样隐式地将指针转换为void *,因为它不知道对于printf()说明符,void *期待%p,因此您应明确将其转换为void *。实际上,您可能需要很长时间才能找到void *int *int (*)[2]int (*)[4][2]不具备完全相同的现代台式计算机表示,但正确胜过不正确。

答案 1 :(得分:0)

您没有指针变量。它是一个数组(表达式),在大多数上下文中内部转换为第一个元素的地址。

指针为int (*arrptr)[4][2] = &array;C FAQ

中的差异很明显
int array[4][2]={1,2,3,4,5,6,7,8};
int (*ptr1)[4][2]=&array;
static int (*ptr2)[4][2];
ptr2=&array;
printf("%p                   %d\n",
        &array[0][0], array[0][0]);
printf("%p    %p      %p     %d\n",
        array,&array, *array,**array);
printf("%p    %p      %p     %d\n",
        ptr1, &ptr1,  *ptr1, ***ptr1);
printf("%p    %p      %p     %d\n",
        ptr2, &ptr2,  *ptr2, ***ptr2);

0xbfbfec24                                1
0xbfbfec24    0xbfbfec24    0xbfbfec24    1
0xbfbfec24    0xbfbfec20    0xbfbfec24    1
0xbfbfec24    0x804970c     0xbfbfec24    1
                      ^^

在这里,您可以看到指针是堆栈中的不同地址,静态指针是堆中更加不同的地址。

答案 2 :(得分:0)

他们不是一回事。

数组是一个由一个或多个连续元素序列组成的对象,所有这些元素都是相同的类型。二维数组不过是一个数组数组。

数组的名称是一个表达式。与任何数组类型的表达式一样,它在大多数但不是所有上下文中都隐式转换为指向数组第一个元素的指针。例外情况是它是sizeof的操作数(sizeof arr产生数组对象的大小而不是指针的大小)以及何时它是一元的操作数{ {1}}(&生成整个数组的地址。)

数组的地址就像任何对象的地址。它指的是一个特定的内存地址,它有一个类型:指向数组类型的指针。例如,给定:

&arr

表达式int arr[10]; (如果它不是arr&的操作数)会产生sizeof的地址,并且类型为{{1} }}。表达式arr[0]产生整个数组的地址;它的内存位置相同,但它的类型为int*,或者&#34;指向10 &arr s&#34;的数组的指针。

数组的通常不是您可以直接引用的内容。它由数组元素的值组成。

现在让我们来看看你的节目:

int (*)[10]

这更明确地写为:

int


#include <stdio.h>
int main(void)
{
    int array[4][2]={1,2,3,4,5,6,7,8};

int array[4][2] = {{1, 2}, {3, 4}, {5, 6}, {7, 8}}; printf("%d %d\n", &array[0][0], array[0][0]); 个对象,因此array[0][0]是其地址,类型为int。打印地址(指针值)的正确方法是使用&array[0][0]格式;它期望一个int*类型的参数,所以你应该转换它。

%p

void*是数组类型的表达式,因此它会衰减&#34;指向该数组的第一个元素的指针。该元素的类型为 printf("%p %d\n", (void*)&array[0][0], array[0][0]); printf("%d %d %d %d\n", array, &array, *array, **array); ,因此指针的类型为array。同样,您应该使用int[2]并转换为int(*)[2]

%p是整个数组的地址。它的类型为void*

&array中,子表达式int(*)[4][2]衰减为指针。 *array然后取消引用该指针,它为我们提供了类型为array的对象(数组的第一个元素)。这是数组类型的表达式,因此它将再次衰减到指向该数组的第一个元素的指针。它的类型为*

int[2]中,int*评估如上;它是指向**array对象的指针。下一个*array取消引用指针,产生int值。

您打印的所有指针值都指向相同的内存地址,但它们的类型分别为*intint*。转换为int(*)[2]时,这些指针中的每一个都会产生相同的值,并且所有指针都会产生

int(*)[2][4]

将这些放在一起,这是您程序的更正版本:

void*

我(64位)系统的输出是:

}

C中的数组和指针之间的关系可能令人困惑。通过阅读comp.lang.c FAQ的第6部分可以清除大部分混淆。

答案 3 :(得分:-3)

Array的内部表示如下。数组只是常量指针。它们表示为连续的存储位置。

Sample example

因此,如果我们将数组作为A[1]访问,则会转换为*(A + 1),即A此处指向第一个元素的地址,1表示偏移量。如果数组类型为int,则1表示sizeof int,例如将int的大小视为4B。因此,A添加了4个字节,现在它将指向数组A中的第二个元素。因此,在2D数组中,它将表示为*(*(A + i) + j),其中i是行,j是列。因此,基于它,您将获得如上所述的输出