更正答案
不,它不会默认为0。这是未定义的行为。在这种情况下,默认值刚好为0,这是优化和编译器的结果。尝试访问未初始化或未分配的内存是未定义的行为。
因为它实际上是“未定义的”,标准对此无法再发表其他声明,你的汇编输出将不会一致。编译器可能会将数组存储在SIMD寄存器中,谁知道输出结果会是什么样子?
来自参考答案的引用:
第四个循环打印了默认数组值0,因为元素3没有初始化
这是最错误的陈述。我猜代码中有错别字,他们想要修改它。
int x[4] = {120, 200, 16};
并错误地将x[4]
变成了x[]
。如果不是故意的,我不知道该说什么了。他们错了。
为什么这不是一个错误?
这不是一个错误,因为这就是堆栈的工作方式。您的应用程序无需在堆栈中分配内存即可使用它,这已经属于您。您可以按照自己的意愿使用堆栈。当您像这样声明变量:
int a;
你所做的只是告诉编译器:“我希望我的堆栈中有4个字节用于a
,请不要将该内存用于其他任何事情。”在编译时查看此代码:
#include <stdio.h>
int main() {
int a;
}
组合语言:
.file "temp.c"
.text
.globl main
.type main, @function
main:
.LFB0:
.cfi_startproc
endbr64
pushq %rbp
.cfi_def_cfa_offset 16
.cfi_offset 6, -16
movq %rsp, %rbp
.cfi_def_cfa_register 6 /* Init stack and stuff */
movl $0, %eax
popq %rbp
.cfi_def_cfa 7, 8
ret /* Pop the stack and return? Yes. It generated literally no code.
All this just makes a stack, pops it and returns. Nothing. */
.cfi_endproc /* Stuff after this is system info, and other stuff
we're not interested. */
.LFE0:
.size main, .-main
.ident "GCC: (Ubuntu 11.1.0-1ubuntu1~20.04) 11.1.0"
.section .note.GNU-stack,"",@progbits
.section .note.gnu.property,"a"
.align 8
.long 1f - 0f
.long 4f - 1f
.long 5
0:
.string "GNU"
1:
.align 8
.long 0xc0000002
.long 3f - 2f
2:
.long 0x3
3:
.align 8
4:
请查看源代码中的注释以获取说明。
因此,您可以看到int x;
没有任何作用。并且如果我打开优化,编译器甚至不会费心制作堆栈并执行所有这些操作,而是直接返回。 int x;
只是一个针对编译器的编译时命令,表示:
x是一个带符号整数的变量。它需要4个字节,请跳过这4个字节(和对齐)后继续声明。
高级语言中(堆栈中)的变量存在的唯一目的是使堆栈的“分布”更加系统化并且以可读的方式进行。变量的声明不是运行时进程。它只是告诉编译器如何在变量之间分配堆栈并相应地准备程序。在执行时,程序将分配堆栈(这是一个运行时进程),但它已经硬编码了哪些变量获得堆栈的哪个部分。例如,变量a
可能获得-0(%rbp)
到-4(%rbp)
,而b
则获得-5(%rbp)
到-8(%rbp)
。这些值在编译时确定。变量的名称也不存在于编译时,它们只是一种告诉编译器如何准备程序以使用其堆栈的方式。
作为用户,您可以自由地使用堆栈;但是您可能不应该这样做。您应该始终声明变量或数组以让编译器知道。
边界检查
在像Go之类的语言中,尽管堆栈是您的,但编译器会插入额外的检查以确保您不会意外使用未声明的内存。出于性能原因,C和C ++不会这样做,并且导致了可怕的未定义行为和段错误更频繁地发生。
堆和数据部分
堆是存储大型数据的地方。没有变量存储在此处,仅存储数据;并且您的一个或多个变量将包含指向该数据的指针。如果您使用未分配的内容(在运行时完成),则会发生段错误。
数据部分是另一个可以存储东西的地方。变量可以存储在此处。它与您的代码一起存储,因此超过分配限制非常危险,因为您可能会意外修改程序的代码。由于它与您的代码一起存储,因此它显然也在编译时分配。实际上,我不太了解数据部分中的内存安全性。显然,您可以超过它而不会引起操作系统的抱怨,但是我对此一无所知,因为我不是系统黑客,也没有使用它进行恶意用途的可疑目的。基本上,我不知道如何超过数据部分的分配限制。希望有人会评论(或回答)。
以上所有汇编代码都是由Ubuntu机器上的GCC 11.1编译的C语言。这是为了提高可读性,而不是C ++。
int x[4] = {120, 200, 16};
会有意义。 - chux - Reinstate Monica