对于下面的代码:
int main()
{
int n;
scanf("%d", &n);
int ar[n];
printf("%d\n", sizeof(ar));
return 0;
}
是可以成立的。
这与之前的C标准有很大不同,以前的数组大小只能由常量来指定,也就是编译器在编译时就可以确定为数组分配多少存储空间,一般来说,一个活动记录的大小在进入一个函数的时候就可以确定下来。这个变长数组的特性必定把数组的分配引入了运行时期,附带的,sizeof这个原来的编译期操作也不得不被带入到运行时期。那么,对于动态数组的实现,编译器必定要生成一些代码来对其进行runtime的支持,这必定有损效率。
GCC编译得到代码
.file "d.c"
.section .rodata.str1.1,"aMS",@progbits,1
.LC0:
.string "%d"
.LC1:
.string "%d\n"
.text
.globl main
.type main, @function
main:
pushl %ebp
movl %esp, %ebp
pushl %ebx
subl $36, %esp
andl $-16, %esp
subl $16, %esp
movl %esp, %ebx
leal -8(%ebp), %eax
movl %eax, 4(%esp)
movl $.LC0, (%esp)
call scanf
movl -8(%ebp), %edx
addl %edx, %edx
addl %edx, %edx
leal 30(%edx), %eax
andl $-16, %eax
subl %eax, %esp
movl %edx, 4(%esp)
movl $.LC1, (%esp)
call printf
movl %ebx, %esp
xorl %eax, %eax
movl -4(%ebp), %ebx
leave
ret
.size main, .-main
.ident "GCC: (GNU) 4.0.3 (Ubuntu 4.0.3-1ubuntu5)"
.section .note.GNU-stack,"",@progbits
省略无关代码
movl -8(%ebp), %edx //n的值
addl %edx, %edx
addl %edx, %edx //edx = edx*4 ,int是4字节的,所以数组占用的空间是4*n
leal 30(%edx), %eax
andl $-16, %eax //字节对齐
subl %eax, %esp //分配存储空间,仍然是在栈里面
这里的空间分配是在栈里完成的
而且没有进行系统调用
所以根本没有额外的碎片所需要的费用
多分配空间是为了进行字节对其