为什么 void *p = &&aa;即使标签 aa 的代码由于 goto 语句而被优化掉,仍然可以编译吗?

问题描述 投票:0回答:1

在C语言中,我想获取一个标签的地址,找到了如下方法: https://gcc.gnu.org/onlinedocs/gcc/Labels-as-Values.html

但是,由于我的代码中存在 goto 语句,发生了奇怪的事情: https://godbolt.org/z/P88MrY5re

#include <string.h>
#include <stdio.h>
int main(){
    void *p = &&aa;
    printf("hello, never execute\n");
    goto end; 
aa:
    printf("new path\n");
end:
    printf("end\n");
    return 0;
}

这是汇编代码:

.LC0:
        .string "hello, never execute"
.LC1:
        .string "end"
main:
        pushq   %rbp
        movq    %rsp, %rbp
        subq    $16, %rsp
.L2:
        movq    $.L2, -8(%rbp)
        movl    $.LC0, %edi
        call    puts
        nop
        movl    $.LC1, %edi
        call    puts
        movl    $0, %eax
        leave
        ret

当我注释掉goto语句时,我正确获取了标签aa的地址: https://godbolt.org/z/P88MrY5re

#include <string.h>
#include <stdio.h>
int main(){
    void *p = &&aa;
    printf("hello, never execute\n");
    //goto end; 
aa:
    printf("new path\n");
end:
    printf("end\n");
    return 0;
}
.LC0:
        .string "hello, never execute"
.LC1:
        .string "new path"
.LC2:
        .string "end"
main:
        pushq   %rbp
        movq    %rsp, %rbp
        subq    $16, %rsp
        movq    $.L2, -8(%rbp)
        movl    $.LC0, %edi
        call    puts
.L2:
        movl    $.LC1, %edi
        call    puts
        movl    $.LC2, %edi
        call    puts
        movl    $0, %eax
        leave
        ret

因此,我想知道当有 goto 语句时,编译器是否已经删除了标签

aa
。我觉得代码
void *p = &&aa;
不应该编译。这是 gcc 中的错误,还是有什么我没有考虑到的? 我查阅了一些资料,也询问了周围的人,但都没有得到我想要的答案。我想知道这是否算作 gcc 中的错误,或者您能为我提供一些资源或想法吗? 谢谢大家!

c pointers label memory-address goto
1个回答
0
投票

虽然编译器确实优化了对

printf("new path\n");
的调用,但它并没有完全删除所有内容。 您会注意到第一个
call puts
指令之后是
nop
。 这就是标签所指向的指令。

此外,如果代码由于打开优化而无法编译,则可能会导致优化器存在错误,因为优化不应影响代码的可观察行为。

© www.soinside.com 2019 - 2024. All rights reserved.