在C语言中,您应该定义数组的长度。但是,以下代码是有效的:
int arr[] = {10, 20, 30, 40, 50};
为什么这种可接受的语法?
答案 0 :(得分:14)
这是一项便利功能。数组的大小是从初始化程序推导出的,因此您不必拼写:
int arr[] = {10, 20, 30, 40, 50};
等同于
int arr[5] = {10, 20, 30, 40, 50};
这的另一个示例(感谢Eugene Sh。)是字符串初始化程序:
char str[] = "asd";
等同于
char str[4] = "asd";
要知道的一件事是,当用作函数参数的类型时,它们是不同的。所有以下形式:
void foo(int v[])
void foo(int v[1])
void foo(int v[5])
void foo(int v[1000])
彼此之间都是等效的,并且将它们转换为:
void foo(int* v)
始终使用后者(void foo(int* v)
),而不要使用其他。因为第一种形式使它看起来像您具有数组类型,但实际上您拥有的是一个指针。这是一种误导。
答案 1 :(得分:6)
要补充现有的答案,请引用C11
,第§6.7.9章,P22
如果初始化了一个未知大小的数组,则其大小由索引最大的数组确定 带有显式初始化程序的元素。数组类型在其末尾完成 初始化程序列表。
因此,数组的大小将由“最大索引元素”决定,或者简单地说,由初始化列表中存在的元素数决定。
答案 2 :(得分:2)
这是可以接受的,因为整数的大小(以字节为单位)在编译期间是已知的,因此编译器知道整个列表需要多少空间。
但是要理解这个答案,必须深入一点,并问为什么在编译时知道确切的大小如此重要。一般而言:为程序定义virtual address space。 其中一部分是用于存储局部变量的堆栈,并且不得将其与堆内存(malloc工作的地方)混淆。堆栈是一个LIFO列表,还包含所有函数调用及其参数。它在函数的末尾用于回跳,即您来自何处,并已存储该地址。在使用函数时,放到堆栈上的所有内容都必须释放,以便获得正确的回跳地址并避免潜在的段错误。
幸运的是,C被视为为我们自动执行了这种类型的内存管理,并在我们所有的automatic variables被认为超出范围后将其释放。要做到这一点,我们需要确切的大小,这就是我们压入堆栈的大小,这就是为什么编译器需要知道该大小的原因。
要说明编译器如何翻译您的代码并对这些数字进行硬编码,请参见此处:
$ echo "int int_size = sizeof(int); int main(void) { int arr[] = {10, 20, 30, 40, 50}; }" |\
gcc -c -xc -S -o- -masm=intel -
.file ""
.intel_syntax noprefix
.text
.globl main
.type main, @function
# [...] removed int_size here to keep it shorter. its "4" ;)
main:
.LFB0:
.cfi_startproc
push rbp # < backup rbp / stack base pointer
.cfi_def_cfa_offset 16
.cfi_offset 6, -16
mov rbp, rsp # < rsp / stack shift pointer = top of the stack
.cfi_def_cfa_register 6
sub rsp, 32
mov rax, QWORD PTR fs:40
mov QWORD PTR -8[rbp], rax
xor eax, eax
mov DWORD PTR -32[rbp], 10 # < 10 is one element from the array
mov DWORD PTR -28[rbp], 20 # < -28 means relative to the top of the stack
mov DWORD PTR -24[rbp], 30
mov DWORD PTR -20[rbp], 40
mov DWORD PTR -16[rbp], 50
mov eax, 0
mov rdx, QWORD PTR -8[rbp]
xor rdx, QWORD PTR fs:40
je .L3
call __stack_chk_fail@PLT
.L3:
leave
.cfi_def_cfa 7, 8
ret
.cfi_endproc
.LFE0:
.size main, .-main
.ident "GCC: (GNU) 8.2.1 20181127"
.section .note.GNU-stack,"",@progbits