c - 了解 C 中数组元素中分配的内存地址(Windows 10 中的 gcc)

标签 c arrays memory pointer-arithmetic

我正在尝试掌握 C 中的指针和数组。现在,我一直在尝试弄清楚我的 C 编译器如何为二维数组中的元素分配内存。这是我的示例代码:

#include <stdio.h>

int main(void)
{
    int ar[2][2] = { {1, 2}, {3, 4} };

    printf("sizeof(int)      = %u\n-----\n", sizeof(int));

    printf("ar               = %p\n", ar);
    printf("ar + 1           = %p\n", ar + 1);
    printf("&ar              = %p\n", &ar);
    printf("&ar + 1          = %p\n\n", &ar + 1);

    printf("sizeof(ar)       = %u\n-----\n", sizeof(ar));

    printf("ar[0]            = %p\n", ar[0]);
    printf("ar[0] + 1        = %p\n", ar[0] + 1);
    printf("&ar[0]           = %p\n", &ar[0]);
    printf("&ar[0] + 1       = %p\n\n", &ar[0] + 1);

    printf("sizeof(ar[0])    = %u\n-----\n", sizeof(ar[0]));

    printf("ar[1]            = %p\n", ar[1]);
    printf("ar[1] + 1        = %p\n", ar[1] + 1);
    printf("&ar[1]           = %p\n", &ar[1]);
    printf("&ar[1] + 1       = %p\n\n", &ar[1] + 1);

    printf("sizeof(ar[1])    = %u\n-----\n", sizeof(ar[1]));

    printf("&ar[0][0]        = %p\n", &ar[0][0]);
    printf("&ar[0][0] + 1    = %p\n", &ar[0][0] + 1);
    printf("&ar[1][0]        = %p\n", &ar[1][0]);
    printf("&ar[1][0] + 1    = %p\n\n", &ar[1][0] + 1);

    printf("sizeof(ar[0][0]) = %u\n-----\n", sizeof(ar[0][0]));

    return 0;
}

我在系统上得到的输出是:

sizeof(int)      = 4
-----
ar               = 0061FF20
ar + 1           = 0061FF28
&ar              = 0061FF20
&ar + 1          = 0061FF30

sizeof(ar)       = 16
-----
ar[0]            = 0061FF20
ar[0] + 1        = 0061FF24
&ar[0]           = 0061FF20
&ar[0] + 1       = 0061FF28

sizeof(ar[0])    = 8
-----
ar[1]            = 0061FF28
ar[1] + 1        = 0061FF2C
&ar[1]           = 0061FF28
&ar[1] + 1       = 0061FF30

sizeof(ar[1])    = 8
-----
&ar[0][0]        = 0061FF20
&ar[0][0] + 1    = 0061FF24
&ar[1][0]        = 0061FF28
&ar[1][0] + 1    = 0061FF2C

sizeof(ar[0][0]) = 4
-----

我明白为什么ar的大小是16字节;它应该能够容纳 4 个 int,在我的系统上是 4x4 = 16 字节。我想,这也是 &ar + 1&ar 之间的字节差异为(十六进制)30 - 20 = 16 的原因。

我不明白的是为什么ar + 1ar之间的差异只有8个字节。这意味着该数组只能容纳 2 ints á 4 个字节。

我在理解 ar[0]ar[1] 时遇到了同样的问题,正如您在我的代码中看到的那样。

ar + 1&ar + 1 不应该产生相同的结果吗?

最佳答案

就您而言,ar 是一个数组。因此,首先请记住

  • arint [2][2] 的类型,它是 int 数组的数组
  • &ar 的类型为 int (*)[2][2],即指向 2 int 数组的数组的指针

也就是说,数组类型在某些情况下会衰减到指向数组第一个元素的指针。注意

所以,如果出现这样的表达式

ar + 1

相同
(&(ar[0])) + 1;

它基本上指向ar[1]

What I don't understand is why the difference between ar + 1 and ar is only 8 bytes

因此,这里的“差异”是 ar[0] 元素占用的大小,即 2 ints,在您的平台中,即 8 个字节。结果检查出来。

另一方面,对于像这样的表达式

&ar + 1;

它对指针类型进行操作(如前所述),并指向数组中最后一个元素之后的位置。因此,差异在于,对于 2 个包含 2 个 int 的数组,因此 (2*2*4) = 16 个字节。


注意:

引用 C11,第 §6.3.2.1 章

Except when it is the operand of the sizeof operator, the _Alignof operator, or the unary & operator, or is a string literal used to initialize an array, an expression that has type ‘‘array of type’’ is converted to an expression with type ‘‘pointer to type’’ that points to the initial element of the array object and is not an lvalue. [....]

关于c - 了解 C 中数组元素中分配的内存地址(Windows 10 中的 gcc),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53479169/

相关文章:

C - 使用 malloc 创建一个数组,然后循环遍历它

c - 如何使用 scanf 检查 '\n'

c++ - C++ 中有 "generics-like"功能吗?

php - 取消设置数组中的索引将它变成一个对象

python - 读取大文件而不重新分配内存

c++ - 直接从数组读取时越界地址

algorithm - long long 除法与 32 位内存

java - Gradle:添加从 Java 到 Native 编译的依赖

php - 在数组中执行一个函数

c - 从 CSV 存储数据时发生访问冲突