【发布时间】:2009-03-22 23:20:23
【问题描述】:
c 如何在运行时找到数组的大小?有关数组大小或数组边界的信息在哪里存储?
【问题讨论】:
c 如何在运行时找到数组的大小?有关数组大小或数组边界的信息在哪里存储?
【问题讨论】:
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,它是一个真正的函数。
【讨论】:
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标准允许实现对它视为常量的内容进行扩展)。
【讨论】:
sizeof 的编译时和非编译时评估,但实际上如何计算可变长度数组的长度?它是存储在数组描述符中还是什么的?
sizeof() 仅适用于固定大小的数组(可以是静态的、基于堆栈的或在结构中)。
如果将其应用于使用malloc(或 C++ 中的新方法)创建的数组,您将始终获得指针的大小。
是的,这是基于编译时间信息。
【讨论】:
sizeof 应该可以工作,即使该数组位于使用 malloc 分配的内存中(可以通过使用指向数组的指针而不是指向元素的指针)。
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)
【讨论】:
struct 定义中。)关键是变量myArray 被声明为array,而不是pointer。因此,编译器看到声明了一个包含 10 个字符的数组,并分配 10 个字节的存储空间来保存这 10 个字符。
myPtr 的情况下,编译器看到的只是一个指针正在被声明;它分配 4 个字节来保存 myPtr(在 32 位机器上),但没有分配任何存储空间供它指向。 myPtr 不是拥有自己独特的内存来存储数据,而是首先指向为myArray 分配的内存。这有帮助吗?
sizeof(Array) 在编译时查找,而不是在运行时查找。信息不会被存储。
您是否对实现边界检查感兴趣?如果是这样,有很多不同的方法可以解决这个问题。
【讨论】: