为什么不在函数内执行printf?

时间:2018-03-13 05:19:34

标签: c arrays function gcc

以下代码编译并在GCC编译器上运行。

#include <stdio.h>

 int arr[10];

 int func()
 {
      printf("In func\n");
      return 0;
 }

int main() 
{
    if (&arr[func()])
        printf("In main\n");
     return 0;
}

输出:

In main

为什么不执行printf("In func\n");

3 个答案:

答案 0 :(得分:3)

似乎存在一个微妙的问题,无论是有意还是无意的最新gcc的各种组合。关于Archlinux上最新内核4.15.8的ver 7.3。无论出于何种原因,为func()生成的代码都省略了对main()的调用。 e.g。

$ gcc -S -masm=intel -o infunc2.asm infunc2.c

生成的程序集是:

$ cat infunc2.asm
        .file   "infunc2.c"
        .intel_syntax noprefix
        .text
        .comm   arr,40,32
        .section        .rodata
.LC0:
        .string "In func"
        .text
        .globl  func
        .type   func, @function
func:
.LFB0:
        .cfi_startproc
        push    rbp
        .cfi_def_cfa_offset 16
        .cfi_offset 6, -16
        mov     rbp, rsp
        .cfi_def_cfa_register 6
        lea     rdi, .LC0[rip]
        call    puts@PLT
        mov     eax, 0
        pop     rbp
        .cfi_def_cfa 7, 8
        ret
        .cfi_endproc
.LFE0:
        .size   func, .-func
        .section        .rodata
.LC1:
        .string "In main"
        .text
        .globl  main
        .type   main, @function
main:
.LFB1:
        .cfi_startproc
        push    rbp
        .cfi_def_cfa_offset 16
        .cfi_offset 6, -16
        mov     rbp, rsp
        .cfi_def_cfa_register 6
        lea     rdi, .LC1[rip]
        call    puts@PLT
        mov     eax, 0
        pop     rbp
        .cfi_def_cfa 7, 8
        ret
        .cfi_endproc
.LFE1:
        .size   main, .-main
        .ident  "GCC: (GNU) 7.3.0"
        .section        .note.GNU-stack,"",@progbits

请注意,func()的来电标记为.LFB0:。尽管main:中存在func字符串,.LFB0:的过程仍然不会调用"In func".LC0:。我怀疑这不是预期的行为。

例如,没有优化-O0的简单编译不会调用该函数,例如:

$ gcc -g -O0 -o bin/if2 infunc2.c
$ ./bin/if2
In main

更改代码以存储arr[func()]的地址会强制调用func(),例如

#include <stdio.h>

int arr[10];

int func()
{
    printf ("In func\n");
    return 0;
}

int main (void)
{
    int *p = &arr[func()];
    if (p)
        printf("In main\n");
    return 0;
}

然后

$ gcc -Wall -Wextra -pedantic -std=gnu11 -Ofast -o bin/infunc infunc.c
$ ./bin/infunc
In func
In main

生成的程序集支持不同的行为:

$ gcc -S -masm=intel -o infunc.asm infunc.c

$ cat infunc.asm
        .file   "infunc.c"
        .intel_syntax noprefix
        .text
        .comm   arr,40,32
        .section        .rodata
.LC0:
        .string "In func"
        .text
        .globl  func
        .type   func, @function
func:
.LFB0:
        .cfi_startproc
        push    rbp
        .cfi_def_cfa_offset 16
        .cfi_offset 6, -16
        mov     rbp, rsp
        .cfi_def_cfa_register 6
        lea     rdi, .LC0[rip]
        call    puts@PLT
        mov     eax, 0
        pop     rbp
        .cfi_def_cfa 7, 8
        ret
        .cfi_endproc
.LFE0:
        .size   func, .-func
        .section        .rodata
.LC1:
        .string "In main"
        .text
        .globl  main
        .type   main, @function
main:
.LFB1:
        .cfi_startproc
        push    rbp
        .cfi_def_cfa_offset 16
        .cfi_offset 6, -16
        mov     rbp, rsp
        .cfi_def_cfa_register 6
        sub     rsp, 16
        mov     eax, 0
        call    func
        cdqe
        lea     rdx, 0[0+rax*4]
        lea     rax, arr[rip]
        add     rax, rdx
        mov     QWORD PTR -8[rbp], rax
        cmp     QWORD PTR -8[rbp], 0
        je      .L4
        lea     rdi, .LC1[rip]
        call    puts@PLT
.L4:
        mov     eax, 0
        leave
        .cfi_def_cfa 7, 8
        ret
        .cfi_endproc
.LFE1:
        .size   main, .-main
        .ident  "GCC: (GNU) 7.3.0"
        .section        .note.GNU-stack,"",@progbits

我希望我能为这里的处理提供一些合理的解释,但我只能记录它。似乎我们需要与gcc列表上的人交谈。

内部地址计算中丢弃的副作用&#39;如果&#39;

这似乎是gcc中的一个回归,它将根据个人发行版是否应用足够的补丁来掩盖它而出现。这是工作中的gcc bug。 Bug 84607

答案 1 :(得分:2)

这是一个gcc错误(#84607),已在gcc 7.3.1或更高版本中修复。

答案 2 :(得分:1)

问题在于您的编译。我用gcc编译。我编译了你的文件:

gcc main.c -o prog
./prog
In func
In main

对我来说似乎很好。如果使用与gcc不同的编译器,请检查如何使用编译器进行编译的过程。我也使用gcc 7.3