首页 文章

使用带有数组和指针的sizeof的实验

提问于
浏览
21

对于该计划:

#include<stdio.h>
int main(void)
{

    int (*a)[2];
    int b[5];

    printf("sizeof(int) : %zu\n", sizeof(int)); 
    printf("sizeof(int*) : %zu\n", sizeof(int*));

    printf("sizeof(b) : %zu\n",sizeof(b));
    printf("sizeof((int*)b) : %zu\n",sizeof((int*)b));
    printf("sizeof(&b[0]) : %zu\n",sizeof(&b[0]));

    printf("sizeof(a) : %zu\n",sizeof(a));
    printf("sizeof(a[0]) : %zu\n",sizeof(a[0]));
    printf("sizeof(a[1]) : %zu\n",sizeof(a[1]));

    return 0;
}

输出是:

sizeof(int) : 4 -> Fact 1
sizeof(int*) : 8 -> Fact 2
sizeof(b) : 20 -> Case 1
sizeof((int*)b) : 8 -> Case 2
sizeof(&b[0]) : 8 -> Case 3
sizeof(a) : 8 -> Case 4
sizeof(a[0]) : 8 -> Case 5
sizeof(a[1]) : 8 -> Case 6

问题/观察(案例顺序):

  • 案例1输出20是因为 b 被声明为整数数组,即 int[] ? Fact1确认返回总块数(以字节为单位) . 不是吗?

  • 我想把 b 投射到 int* 这里有所不同 . 这里 b 被认为是一个指针 . 我使用Fact2证实了这一点 . 对还是错?

  • &b[0] 衰减到指针 b . 输出与Fact2一致 .

  • expected 16这里但输出为8 . 我的结论是,这是因为 a 是一个指针,输出与Fact2重合 . 我的输出类似于问题2 .

  • a[0] 是指针 . 输出与Fact2一致

  • a[1] 是指针 . 输出与Fact2一致

如果任何观察结果有误,请回答问题并纠正我 .

3 回答

  • 2

    如果任何观察结果有误,请回答问题并纠正我 . 情况1输出20是因为b被声明为整数数组,即int []? Fact1确认返回总块数(以字节为单位) . 不是吗?

    是的,结果显示 sizeof(int [5]) . 所以从Fact1,大小是 5*4

    我想把b转换成int *在这里有所不同 . 这里b被认为是一个指针 . 我使用Fact2证实了这一点 . 对还是错?

    对 . 但是添加更多信息: sizeof 只需要表达式的类型,并且 does not 评估表达式(用于值),除非它是VLA类型 . (来自C99 specs6.5.3.4 The sizeof operator 部分)

    因为您在最终结果上应用演员表,所以之后的任何事情都无关紧要 .

    &b [0]衰减到指针b . 输出与Fact2一致 .

    不,是的 . b[0] 的类型是 int ,因此 &b[0] 的类型已经 int * (回想 [...]& 更紧密地绑定) . 没有腐朽 . 是的,输出与Fact2重合 .

    我在这里预计16,但我得到了8作为输出 . 我的结论是,这是因为a是一个指针,输出与Fact2重合 . 我的输出类似于问题2 .

    a 作为指向 int 的数组2的指针 . 所以打印的大小是指针(到 int 数组) .

    int (*a)[2]; 声明 a 作为指向 int 的数组2的指针 . 所以你得到 pointer to array 的大小 .

    要获得所需的结果(指针数组2的大小为 int ),请使用: int *a[2];

    int (*a)[2];
    
    a           anonymous
    +----+      +----+----+
    | a  |----->|int |int |
    +----+      +----+----+
    
    int *b[2];
    
    b  
    +----+----+
    |int*|int*|
    +----+----+
    b[0] b[1]
    

    a [0]是指针 . 输出与Fact2一致[a]是指针 . 输出与Fact2一致

    如前所述, a 是指向 int 的数组2的指针 . 所以 a[index]int 的数组2 . 因此, a[0]a[1] 的类型是 int 的数组2 . 所以输出是事实1的 2*4 .
    可能与此答案无关,但 a 未初始化并在表达式中使用它会导致undefined behaviour . 虽然可以在 sizeof 中使用


    要理解输出,让我们分析 sizeof 的参数类型

    printf("sizeof(b) : %zu\n",sizeof(b));             // int [5]
    printf("sizeof((int*)b) : %zu\n",sizeof((int*)b)); // int *
    printf("sizeof(&b[0]) : %zu\n",sizeof(&b[0]));     // int *
    
    printf("sizeof(a) : %zu\n",sizeof(a));             // int (*) [2]
    printf("sizeof(a[0]) : %zu\n",sizeof(a[0]));       // int [2]
    printf("sizeof(a[1]) : %zu\n",sizeof(a[1]));       // int [2]
    

    portable program (not foolproof) to confirm the types看起来像:

    assert(sizeof(b) == sizeof(int [5]));
    assert(sizeof((int*)b) == sizeof(int *));
    assert(sizeof(&b[0]) == sizeof(int *));
    
    assert(sizeof(a) == sizeof(int(*)[2]));
    assert(sizeof(a[0]) == sizeof(int[2]));
    assert(sizeof(a[1]) == sizeof(int[2]));
    
  • 13

    sizeof 运算符是可以区分数组(假设它不是函数参数)和指针的少数事物之一 .

    • b 被识别为5个元素的数组,每个元素都是4个字节,因此 sizeof(b) 的计算结果为20 .

    • 强制转换将数组转换为指针的方式与将函数传递给函数的方式类似 . 所以大小是8 .

    • 这实际上并没有衰减到指针 . 这是一个指针 . 你正在获取 int 的地址,所以当然类型是 int * . 解决你的一条评论,如果将表达式 &b[0] 衰减到一个指针,如果将它传递给一个函数仍然是不准确的,因为它实际上是一个指针,而不是一个数组 .

    • 由于 a 是指向数组的指针,因此大小是指针的大小,即8.这与 int *c[2] 不同,后者是一个指针数组,大小为16 .

    • a[0] 不是指针,而是大小为2的数组 . 语法 a[0] 等同于 *(a + 0) . 因为 a 是一个指向数组的指针,所以取消引用 a 会给我们一个数组 . 由于每个元素是4个字节,因此大小为8.如果 a 被定义为 int (*a)[3] ,那么 sizeof(a[0]) 的计算结果为12 .

    • 与数字5类似, a[1] 是一个大小为2的数组 . 因此, sizeof(a[1]) 的计算结果为8,因为它是一个包含4个大小为4的元素的数组 .

    如何使用 a 的示例如下:

    int (*a)[2];
    int d[3][2];
    
    a=d;
    d[0][0]=1;
    d[0][1]=2;
    d[1][0]=3;
    d[1][1]=4;
    d[2][0]=5;
    d[3][1]=6;
    
    printf("a00=%d\n",a[0][0]);
    printf("a01=%d\n",a[0][1]);
    printf("a10=%d\n",a[1][0]);
    printf("a11=%d\n",a[1][1]);
    printf("a20=%d\n",a[2][0]);
    printf("a21=%d\n",a[3][1]);
    

    输出:

    a00=1
    a01=2
    a10=3
    a11=4
    a20=5
    a21=6
    

    将2D数组传递给函数时也可以使用它:

    void f(int (*a)[2]) 
    {
        ...
    }
    
    int main()
    {
        int x[3][2];
        f(x);
    }
    
  • 15

    这是关于这个主题的一些个人研究 . 我在四种不同的环境中运行您的测试代码,两个64位和两个32位 .
    我使用了三种不同的编译器:llvm,gcc和mipsPro cc .
    这是评论 comparison of the results

    // 64-bit environment - all compilers
    sizeof(int) :     4 -> Fact 1       -32 bit int -> 4 bytes   
    sizeof(int*) :    8 -> Fact 2       -this and other pointers in a 64-bit system are 8-bytes long
    sizeof(b) :      20 -> Case 1       -array of 5 32 bit ints -> 20 bytes
    sizeof((int*)b) : 8 -> Case 2
    sizeof(&b[0]) :   8 -> Case 3
    sizeof(a) :       8 -> Case 4
    sizeof(a[0]) :    8 -> Case 5       -array of two 4 byte ints
    sizeof(a[1]) :    8 -> Case 6       -array of two 4 byte ints
    
    // 32-bit environments - all compilers
    sizeof(int) :     4 -> Fact 1       -32 bit int -> 4 bytes 
    sizeof(int*) :    4 -> Fact 2       -this and other pointers in a 32-bit system are 4-bytes long
    sizeof(b) :      20 -> Case 1       -array of 5 32 bit ints -> 20 bytes
    sizeof((int*)b) : 4 -> Case 2
    sizeof(&b[0]) :   4 -> Case 3
    sizeof(a) :       4- > Case 4
    sizeof(a[0]) :    8 -> Case 5       -array of two 4 byte ints
    sizeof(a[1]) :    8 -> Case 6       -array of two 4 byte ints
    

    Interpretation - 所有结果始终符合以下模式:

    • int 的大小曾经依赖于编译器,也许仍然依赖于AFAIK . 它在所有测试环境和编译器中都是4字节(事实1) .

    • 所有指针的大小默认为环境,64位或32位(事实2,案例2,3,4) .

    • 两个四字节整数的数组大小等于 2*sizeof(int) (情况5,6) .

    • a[0] 可以改写为 *a ; a[1] 也可以写成 *(a + 1) . 以下SO post详细阐述了它 .

    希望这可以为您的主题做出贡献 .

相关问题