GCC扩展名__attribute__((未使用))用于变量属性

时间:2018-11-15 15:03:19

标签: c gcc gcc-extensions

以下是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中未使用和使用过的变量属性的工作。

谢谢

2 个答案:

答案 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 旨在用于变量(但我认为也适用于函数),以便为汇编代码生成变量。即使它在任何地方都没有使用过。