&&在无效* p = && abc;中是什么意思


102

我遇到了一段代码void *p = &&abc;&&这里的意义是什么?我知道右值引用,但我认为&&在这种情况下使用的是不同的。&&表示什么void *p = &&abc;


14
您在哪里看到的?
user541686 2011年

3
我也想知道你在哪里看到的。
Flavius

Answers:


154

&&是gcc的扩展名,用于获取当前函数中定义的标签的地址。

void *p = &&abc 在标准C99和C ++中是非法的。

这个编译使用g ++。


42
现在想象一下,如果默认情况下gcc使用-pedantic,那么每个人都会有更好的程序员。然后人们将学习C而不是有关gnus的无关信息。
伦丁

4
真是可笑。如果他们发明了标签指针的新语法,则也应该为其发明一个新类型,而不是使用void*
Mark Ransom

1
@Prasoon Saurav:投票否决的人可能不赞成该功能,并将其淘汰给您。
查克(Chuck)

@Lundin:大多数编译器都可以这样说。__forceinline__declspec(naked)?我最喜欢的MSVCism之一是:template<typename T> class X { friend T; },它是无效的C ++ 03。
塞巴斯蒂安·马赫

第二个链接已死。
心教堂

96

如何找出来

那是标签的地址,这是GCC特有的功能。

int main(void) {
    void* startp;
s:
    startp = &&s;
    printf("the assignment above starts at address %p\n", startp);
    return 0;
}

您可以通过测试自己弄清楚:

int main(void) {
    void* startp;
    int a;
    startp = &&a;
    printf("startp=%p\n", startp);
    return 0;
}

在这种情况下,GCC会说:

错误:使用了标签“ a”但未定义

引擎盖下-组装

您需要知道汇编程序才能真正理解这一点,但是我将尽力向您解释标签地址的含义。

操作系统从磁盘加载.exe文件后,操作系统的一个组件称为“加载程序”(Windows具有“ PE加载程序”,Linux具有“ ELF加载程序”,甚至其他,如果它们是在内核),它将对该程序进行“虚拟化”,然后将其变成一个进程。

该进程认为它是RAM中唯一的一个,并且可以访问整个RAM(即32位计算机上的0x00000000-0xFFFFFFFF)。

(以上只是对情况的简短介绍,您确实需要学习汇编才能完全理解它,所以请多多包涵)

现在,源代码中的标签基本上是一个地址。“转到标签;” 除了跳转到该地址外,别无其他(想想汇编中的指令指针)。该标签存储该RAM地址,这就是您找出该地址的方法。

学习了ASM之后,您将意识到该地址指向.text可执行文件部分中的一条指令。该.text部分是保存要执行的程序(二进制)代码的部分。

您可以使用以下方法进行检查:

objdump -x a.out

一个实际的例子

GCC中所述,您可以使用它来初始化跳转表。一些扫描仪生成器(re2c(请参阅-g参数))使用它来生成更紧凑的扫描仪。也许甚至有使用相同技术的解析器生成器


4
使用-std = c99 -pedantic进行编译。
伦丁

2
非常重要的一点是,它是GCC扩展,而不是语言的核心部分
杰夫(Jalf)

1
多数民众赞成在黄蜂。
2011年

1
我喜欢这种答案,需要教会更多的人如何找到答案,而不仅仅是被告知。
Letseatlunch 2011年

1
感谢您的深入解释。赞赏大会相关分析。
CᴴᴀZ
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.