根据当前的 C 标准,分配给已声明但未定义的 `int` 的默认值是多少?
According to the current C Standard, what is the default value assigned to an `int` which is declared but not defined?
C标准问题
简单的问题,但似乎无法通过 duckduckgo 或搜索 SO(此处)找到答案。
我知道在 C 中,标准规定未初始化的 int
数组会导致未定义的行为。 (或者至少大多数编译器都是这样的。)
int a[100]; // 100 x 32bits on stack, values are whatever was left over on the stack
printf("a[5]=%d", a[5]); // undefined behaviour, can be any valid `int` value (-2**15 to 2**15 - 1)
但是,单个int
的默认值是多少?
int 一个;
printf("a=%d", a);
我的猜测是,因为它在堆栈上,所以 CPU 必须执行“压栈”指令,并且该指令必须取一个值,并且对于 a 最合理的值如果未指定值,则使用的编译器将为零。
我说得对吗?
示例测试程序和反汇编
#include <stdio.h>
int a;
int main(void)
{
printf("%d\n", a);
return 0;
}
这是这个反汇编:(`gcc -save-temps -Wall test.c -o test)
.file "test.c"
.text
.globl a
.bss
.align 4
.type a, @object
.size a, 4
a:
.zero 4
.section .rodata
.LC0:
.string "%d\n"
.text
.globl main
.type main, @function
main:
.LFB0:
.cfi_startproc
pushq %rbp
.cfi_def_cfa_offset 16
.cfi_offset 6, -16
movq %rsp, %rbp
.cfi_def_cfa_register 6
movl a(%rip), %eax
movl %eax, %esi
leaq .LC0(%rip), %rdi
movl [=12=], %eax
call printf@PLT
movl [=12=], %eax
popq %rbp
.cfi_def_cfa 7, 8
ret
.cfi_endproc
.LFE0:
.size main, .-main
.ident "GCC: (Debian 10.2.1-6) 10.2.1 20210110"
.section .note.GNU-stack,"",@progbits
这似乎有行
a:
.zero 4
这是否意味着a在.data
部分被初始化为4x0x00
(字节)的内存块?
在你的例子中
#include <stdio.h>
int a;
int main(void)
{
printf("%d\n", a);
return 0;
}
变量a
是全局声明的,所以初始化为0。
另一方面,如果变量 a
是局部非静态声明的
#include <stdio.h>
int main(void)
{
int a;
printf("%d\n", a);
return 0;
}
它有一个不确定的值,使用该值会调用 未定义的行为。
引自N1570 6.7.9 初始化 10:
If an object that has automatic storage duration is not initialized explicitly, its value is
indeterminate. If an object that has static or thread storage duration is not initialized
explicitly, then:
— if it has pointer type, it is initialized to a null pointer;
— if it has arithmetic type, it is initialized to (positive or unsigned) zero;
— if it is an aggregate, every member is initialized (recursively) according to these rules,
and any padding is initialized to zero bits;
— if it is a union, the first named member is initialized (recursively) according to these
rules, and any padding is initialized to zero bits;
C标准问题
简单的问题,但似乎无法通过 duckduckgo 或搜索 SO(此处)找到答案。
我知道在 C 中,标准规定未初始化的 int
数组会导致未定义的行为。 (或者至少大多数编译器都是这样的。)
int a[100]; // 100 x 32bits on stack, values are whatever was left over on the stack
printf("a[5]=%d", a[5]); // undefined behaviour, can be any valid `int` value (-2**15 to 2**15 - 1)
但是,单个int
的默认值是多少?
int 一个; printf("a=%d", a);
我的猜测是,因为它在堆栈上,所以 CPU 必须执行“压栈”指令,并且该指令必须取一个值,并且对于 a 最合理的值如果未指定值,则使用的编译器将为零。
我说得对吗?
示例测试程序和反汇编
#include <stdio.h>
int a;
int main(void)
{
printf("%d\n", a);
return 0;
}
这是这个反汇编:(`gcc -save-temps -Wall test.c -o test)
.file "test.c"
.text
.globl a
.bss
.align 4
.type a, @object
.size a, 4
a:
.zero 4
.section .rodata
.LC0:
.string "%d\n"
.text
.globl main
.type main, @function
main:
.LFB0:
.cfi_startproc
pushq %rbp
.cfi_def_cfa_offset 16
.cfi_offset 6, -16
movq %rsp, %rbp
.cfi_def_cfa_register 6
movl a(%rip), %eax
movl %eax, %esi
leaq .LC0(%rip), %rdi
movl [=12=], %eax
call printf@PLT
movl [=12=], %eax
popq %rbp
.cfi_def_cfa 7, 8
ret
.cfi_endproc
.LFE0:
.size main, .-main
.ident "GCC: (Debian 10.2.1-6) 10.2.1 20210110"
.section .note.GNU-stack,"",@progbits
这似乎有行
a:
.zero 4
这是否意味着a在.data
部分被初始化为4x0x00
(字节)的内存块?
在你的例子中
#include <stdio.h>
int a;
int main(void)
{
printf("%d\n", a);
return 0;
}
变量a
是全局声明的,所以初始化为0。
另一方面,如果变量 a
是局部非静态声明的
#include <stdio.h>
int main(void)
{
int a;
printf("%d\n", a);
return 0;
}
它有一个不确定的值,使用该值会调用 未定义的行为。
引自N1570 6.7.9 初始化 10:
If an object that has automatic storage duration is not initialized explicitly, its value is
indeterminate. If an object that has static or thread storage duration is not initialized
explicitly, then:
— if it has pointer type, it is initialized to a null pointer;
— if it has arithmetic type, it is initialized to (positive or unsigned) zero;
— if it is an aggregate, every member is initialized (recursively) according to these rules,
and any padding is initialized to zero bits;
— if it is a union, the first named member is initialized (recursively) according to these
rules, and any padding is initialized to zero bits;