You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

GCC -O0编译时C数组汇编代码异常问题咨询

Understanding GCC -O0 Stack Allocation Behavior for Unused Arrays

Let's walk through each of your observations and answer your questions—these aren't bugs, they're intentional choices in GCC's stack frame layout when using -O0 (minimal optimization), plus key differences between x86_64 and 32-bit x86 (i386) ABIs.

1. char test[50]; (x86_64) doesn't allocate stack space

Your code:

int square() { char test[50]; }

Generated assembly:

square():
 push rbp
 mov rbp, rsp

Why this happens:

First, your test array is completely unused—no reads, writes, or references to it anywhere. Even with -O0, GCC does minimal dead-code cleanup: since the array has no impact on program behavior, GCC simply ignores it. No need to allocate stack space for something that's never used.

Second, x86_64's System V ABI defines a 128-byte "red zone" below the stack pointer (rsp). This area is guaranteed to not be clobbered by signal handlers or asynchronous calls. Even if you did use the 50-byte array, GCC could access it via offsets from rbp/rsp without explicitly adjusting the stack pointer (since 50 bytes fits well within the red zone).

2. char test[150]; (x86_64) allocates only 40 bytes

Your code:

int square() { char test[150]; }

Generated assembly:

square():
 push rbp
 mov rbp, rsp
 sub rsp, 40

Why this happens:

Again, the 150-byte array is unused, so GCC isn't allocating space for it. The sub rsp, 40 is for stack alignment and minimal stack frame overhead.

x86_64 requires the stack pointer to be 16-byte aligned when calling functions. After push rbp (which subtracts 8 bytes from the 16-byte-aligned stack) and mov rbp, rsp, rsp is 8-byte aligned. The sub rsp, 40 brings rsp back to a 16-byte alignment (8 + 40 = 48, a multiple of 16) and reserves small scratch space—this has nothing to do with the unused array.

3. char a[50]; char b[50]; (x86_64) allocates only 8 bytes

Your code:

int square() { char a[50]; char b[50]; }

Generated assembly:

square():
 push rbp
 mov rbp, rsp
 sub rsp, 8

Why this happens:

Same core logic: both arrays are unused, so GCC doesn't allocate space for them. The sub rsp, 8 is purely for stack alignment—after push rbp, rsp is 8-byte aligned; subtracting another 8 bytes makes it 16-byte aligned, satisfying the x86_64 ABI's requirement.

4. char a[500]; (-m32) allocates 512 bytes (12 bytes more than expected)

Your code:

int square() { char a[500]; }

Generated assembly (32-bit x86):

square():
 push ebp
 mov ebp, esp
 sub esp, 512

Why this happens:

32-bit x86 has no red zone, so all local variables require explicit stack allocation. The extra 12 bytes come from stack alignment:
GCC aligns stack frames to 16-byte boundaries even in 32-bit mode (for compatibility with SIMD instructions and ABI conventions). 500 rounded up to the next multiple of 16 is 512—those 12 bytes are just padding to reach that alignment.

Key Question: Why does -m32 char test[50]; generate a sub instruction but x86_64 doesn't?

The main difference is the red zone in x86_64's ABI:

  • In x86_64, the 128-byte red zone below rsp is safe for small local variables. Even if your 50-byte array were used, GCC could access it via offsets from rbp/rsp without adjusting rsp. And since your array is unused, GCC skips allocation entirely.
  • In 32-bit x86, there is no red zone. All local variables need explicit stack space allocated via sub esp, even for small arrays. Plus, GCC may allocate minimal alignment space even for unused variables in 32-bit mode to maintain consistent stack frame structure.

内容的提问来源于stack exchange,提问作者user282909

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.06 16:27:48