【问题标题】:How Does sizeof(Array) worksizeof(Array) 是如何工作的
【发布时间】:2009-03-22 23:20:23
【问题描述】:

c 如何在运行时找到数组的大小?有关数组大小或数组边界的信息在哪里存储?

【问题讨论】:

    标签: c arrays


    【解决方案1】:

    sizeof(array) 完全由 C 编译器实现。当程序被链接时,看起来像 sizeof() 的调用已转换为常量。

    示例:当你编译这段 C 代码时:

    #include <stdlib.h>
    #include <stdio.h>
    int main(int argc, char** argv) {
        int a[33];
        printf("%d\n", sizeof(a));
    }
    

    你得到

        .file   "sz.c"
        .section        .rodata
    .LC0:
        .string "%d\n"
        .text
    .globl main
        .type   main, @function
    main:
        leal    4(%esp), %ecx
        andl    $-16, %esp
        pushl   -4(%ecx)
        pushl   %ebp
        movl    %esp, %ebp
        pushl   %ecx
        subl    $164, %esp
        movl    $132, 4(%esp)
        movl    $.LC0, (%esp)
        call    printf
        addl    $164, %esp
        popl    %ecx
        popl    %ebp
        leal    -4(%ecx), %esp
        ret
        .size   main, .-main
        .ident  "GCC: (GNU) 4.1.2 (Gentoo 4.1.2 p1.1)"
        .section        .note.GNU-stack,"",@progbits
    

    中间的$132 是数组的大小,132 = 4 * 33。注意没有call sizeof 指令——不像printf,它是一个真正的函数。

    【讨论】:

      【解决方案2】:

      sizeof 是 C99 之前的 C++ 和 C 中的纯编译时间。从 C99 开始有可变长度数组:

      // returns n + 3
      int f(int n) {
          char v[n + 3];
      
          // not purely a compile time construct anymore
          return sizeof v;
      }
      

      这将评估sizeof 操作数,因为n 在编译时还不知道。 only 适用于可变长度数组:其他操作数或类型仍然在编译时计算 sizeof。特别是,在编译时已知维度的数组仍然像在 C++ 和 C89 中一样处理。因此,sizeof 返回的值不再是编译时常量(常量表达式)。你不能在需要这样一个值的地方使用它——例如在初始化静态变量时,除非编译器特定的扩展允许它(C标准允许实现对它视为常量的内容进行扩展)。

      【讨论】:

      • 很高兴你提到了 C99 VLA。但是,您的回答应该强调,即使在 C99 中,固定大小的数组也会在编译时计算其大小——只有 VLA 在运行时计算其大小。因此,也许你不能总是在 C99 中使用 'sizeof(array)' 作为常量。
      • 好的,现在该睡觉了。稍后我会醒来并为我的答案中的所有错别字尖叫:p
      • +1 用于区分 C99 中 sizeof 的编译时和非编译时评估,但实际上如何计算可变长度数组的长度?它是存储在数组描述符中还是什么的?
      【解决方案3】:

      sizeof() 仅适用于固定大小的数组(可以是静态的、基于堆栈的或在结构中)。

      如果将其应用于使用malloc(或 C++ 中的新方法)创建的数组,您将始终获得指针的大小。

      是的,这是基于编译时间信息。

      【讨论】:

      • 固定大小的数组不一定是基于堆栈的。 C 没有 new 运算符。
      • 您已经忘记了 C99 VLA - 可变长度数组。
      • "Array" 在 C 类型系统中具有相当特殊的含义。如果您有一个 array (不是指针),sizeof 应该可以工作,即使该数组位于使用 malloc 分配的内存中(可以通过使用指向数组的指针而不是指向元素的指针)。
      【解决方案4】:

      sizeof 给出变量的大小,而不是你指向的对象的大小(如果有的话)。sizeof(arrayVar) 将返回数组大小(以字节为单位)当且仅当 arrayVar 是在作用域中声明为数组而不是指针。

      例如:

      char myArray[10];
      char* myPtr = myArray;
      
      printf("%d\n", sizeof(myArray)) // prints 10 
      printf("%d\n", sizeof(myPtr)); // prints 4 (on a 32-bit machine)
      

      【讨论】:

      • 你能详细说明为什么排名第一的人给了 10 分吗?是在堆栈还是堆中?
      • 它是在堆栈中还是在堆中都没有关系(尽管要在堆中,它必须嵌入到struct 定义中。)关键是变量myArray 被声明为array,而不是pointer。因此,编译器看到声明了一个包含 10 个字符的数组,并分配 10 个字节的存储空间来保存这 10 个字符。
      • 在myPtr 的情况下,编译器看到的只是一个指针正在被声明;它分配 4 个字节来保存 myPtr(在 32 位机器上),但没有分配任何存储空间供它指向。 myPtr 不是拥有自己独特的内存来存储数据,而是首先指向为myArray 分配的内存。这有帮助吗?
      【解决方案5】:

      sizeof(Array) 在编译时查找,而不是在运行时查找。信息不会被存储。

      您是否对实现边界检查感兴趣?如果是这样,有很多不同的方法可以解决这个问题。

      【讨论】:

        猜你喜欢
        • 2012-04-22
        • 2016-06-25
        • 1970-01-01
        • 2019-01-01
        • 2019-03-12
        • 2014-06-07
        • 2020-08-20
        • 1970-01-01
        相关资源
        最近更新 更多