以下是GCC变量属性扩展的示例代码,
#include<stdio.h>
int main(void){
int sam __attribute__((unused))= 10;
int p = sam+1;
printf("\n%d" , p);
}
使用以下命令生成的上述程序的汇编代码:
gcc -S sample.c
.s文件中没有包含变量sam,而程序的输出为“ 11”,这是正确的。 那么,编译器会完全忽略未使用的变量,而不将其输出到可执行文件中吗?如果是这样,为什么程序输出正确?谁能解释gcc中未使用和使用过的变量属性的工作。
谢谢
答案 0 :(得分:1)
尝试在没有优化的情况下编译
gcc -O0 sample.c -S -masm=intel
生成的汇编代码
.file "sample.c"
.intel_syntax noprefix
.text
.def __main; .scl 2; .type 32; .endef
.section .rdata,"dr"
.LC0:
.ascii "\12%d\0"
.text
.globl main
.def main; .scl 2; .type 32; .endef
.seh_proc main
main:
push rbp
.seh_pushreg rbp
mov rbp, rsp
.seh_setframe rbp, 0
sub rsp, 48
.seh_stackalloc 48
.seh_endprologue
call __main
mov DWORD PTR -4[rbp], 10
mov eax, DWORD PTR -4[rbp]
add eax, 1
mov DWORD PTR -8[rbp], eax
mov eax, DWORD PTR -8[rbp]
mov edx, eax
lea rcx, .LC0[rip]
call printf
mov eax, 0
add rsp, 48
pop rbp
ret
.seh_endproc
.ident "GCC: (GNU) 10.2.0"
.def printf; .scl 2; .type 32; .endef
答案 1 :(得分:1)
所以编译器完全忽略了未使用的变量
取决于您所说的“忽视”是什么意思。编译器会优化代码,但不会完全忽略变量,否则编译器无法计算结果。
<块引用>不在可执行文件中输出?
是的。
<块引用>如果是这样,为什么程序的输出是正确的?
因为这是编译器所做的 - 生成具有编程语言描述的输出的程序。代码与汇编不是一对一的,代码是一种描述程序行为的语言。理论上,只要编译程序的输出与源代码中的内容一致,编译器就可以生成它想要的任何汇编指令。
您可能想在 C 编程语言的上下文中研究术语副作用和as-if规则。
<块引用>谁能解释一下 gcc 中未使用和使用过的变量属性的工作原理。
没有比 GCC documentation about Variable Attributes 更好的解释了:
<块引用>未使用
<块引用>附加到变量的此属性意味着该变量可能未使用。 GCC 不会为此变量生成警告。
使用过
<块引用>此属性附加到具有静态存储的变量上,意味着即使该变量看起来没有被引用,也必须发出该变量。
当应用于 C++ 类模板的静态数据成员时,该属性还意味着如果类本身被实例化,则该成员也被实例化。
属性 unused
是将编译器警告从 -Wunused-*
警告中静音。
属性 used
旨在用于变量(但我认为也适用于函数),以便为汇编代码生成变量。即使它在任何地方都没有使用过。