以下是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中未使用和已使用的变量属性的工作原理吗。
感谢
编译器是否完全忽略了未使用的变量
取决于您所说的";忽视";。编译器优化代码,但不会完全忽略变量,否则编译器无法计算结果。
是否在可执行文件中输出?
是。
如果是,为什么程序的输出正确?
因为这就是编译器所做的-生成具有编程语言所述输出的程序。代码不是程序集的1:1,代码是描述程序的行为的语言。理论上,只要编译程序的输出与源代码中的内容正确,编译器就可以生成它想要的任何汇编指令。
您可能想在C编程语言的上下文中研究术语副作用和好像规则。
任何人都能解释gcc中未使用和已使用的变量属性的工作原理吗。
没有比GCC文档中关于变量属性更好的解释了:
未使用的
此属性附加到变量,表示该变量可能未使用。GCC不会对此变量产生警告。
使用
此属性附加到具有静态存储的变量,意味着即使变量看起来没有被引用,也必须发出该变量。
当应用于C++类模板的静态数据成员时,该属性还意味着,如果类本身被实例化,则该成员被实例化。
属性unused
用于从-Wunused-*
警告中消除编译器警告。
属性used
用于变量(但我认为也适用于函数(,以便将变量生成为汇编代码。即使它在任何地方都没有被使用。
尝试在没有优化的情况下进行编译
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 "
.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