Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/arrays/14.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C 为什么数组的名称、地址和数组的值都是相同的?_C_Arrays_Memory Address - Fatal编程技术网

C 为什么数组的名称、地址和数组的值都是相同的?

C 为什么数组的名称、地址和数组的值都是相同的?,c,arrays,memory-address,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

这是一个二维数组。我知道数组的名称指向数组中的第一个元素,即&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);
}

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

指针应该是
int(*arrptr)[4][2]=&array。这种差异在本文中得到了很好的解释


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

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

因此,如果我们以
A[1]
的形式访问数组,它将转换为
*(A+1)
,即
A
这里指向第一个元素的地址,1表示偏移量。如果数组是<代码> int <代码>,那么1代表<<代码>代码> >代码>。因此,4个字节被添加到
A
,现在它将指向数组
A
中的第二个元素。因此,在2D数组中,它将表示为
*(*(A+i)+j)
,其中
i
是行,
j
是列。因此,在此基础上,您将在代码中获得上述输出(已更正):

应向您发出警告,同时:

int (*p)[2] = array;
不应该

然而,由于数组在内存中的布局方式,
array
的地址与
array[0]
的地址相同,后者与
array[0][0]
的地址相同

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

  • *数组
    相当于
    数组[0]
    数组[0]
    的类型是大小为
    2
    int
    数组。由于
    数组[0]
    本身就是一个数组,因此它在此处也会衰减为指向其第一个元素的指针,正如所解释的那样,该元素与
    数组
    的地址相同,而
    数组
    的地址在此处衰减为

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

  • 这就是为什么前三个表达式都计算到相同的地址


    请注意,
    %p
    用于指针,由于
    printf()
    是一个可变函数,编译器无法像通常那样将指针隐式转换为
    void*
    ,因为它不知道
    printf()
    需要
    void*
    作为
    %p
    说明符,因此,您应该显式地将它们强制转换为
    void*
    。实际上,你可能要花很长时间才能找到一台现代台式计算机,其中
    void*
    int*
    int(*)[2]
    、和
    int(*)[4][2]
    没有完全相同的表示形式,但正确总比不正确好。

    它们不是一回事

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

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

    数组的地址类似于任何对象的地址。它引用一个特定的内存地址,它有一个类型:指向数组类型的指针。例如,假设:

    int arr[10];
    
    表达式
    arr
    (如果它不是
    &
    sizeof
    的操作数)生成
    arr[0]
    ,类型为
    int*
    。表达式
    &arr
    生成整个数组的地址;它是相同的内存位置,但类型为
    int(*)[10]
    ,或“指向10
    int
    s数组的指针”

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

    现在让我们看看您的程序:

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

    array[0][0]
    是一个
    int
    对象,因此
    &array[0][0]
    是它的地址,类型为
    int*
    。打印地址(指针值)的正确方法是使用
    %p
    格式;它需要一个类型为
    void*
    的参数,因此您应该转换它

        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*

    **数组
    中,
    *数组
    的评估如上所述;它是指向
    int
    对象的指针。下一个
    *
    取消对
    int arr[10];
    
    #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]);
    
        printf("%p    %d\n", (void*)&array[0][0], array[0][0]);
    
        printf("%d    %d    %d    %d\n",
               array, &array, *array, **array);
    
    }
    
    #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);
    }