我正在玩标签作为值,并以此代码结束。
int foo = 0; goto * foo;我的C / C ++经验告诉我 * foo 意味着 dereference foo ,并且这不会被编译,因为 foo 不是一个指针。但它确实编译。这实际上是做什么的?
gcc(Ubuntu 4.9.2-0ubuntu1〜12.04)4.9.2 ,if
解决方案这是gcc中已知的一个bug。 gcc的文档扩展名允许表单的声明
goto * ptr;其中 ptr 可以是任何类型的表达式 void *的。作为该扩展的一部分,对标签名称应用一个&& 产生标签的地址,类型为 void * $在您的示例中:
int foo = 0; goto * foo;foo 显然是 int ,而不是类型 void * 。一个 int 值可以被转换为 void * ,但只能用明确的转换(除了特殊情况空白指针常量,这里不适用)。 $ b $
表达式 * foo 本身被正确诊断为错误。这个:
goto * 42;无错地编译(生成的机器代码似乎是跳转到地址 42 ,如果我正确读取汇编代码)。
快速实验表明gcc为
goto * 42;如同它为
goto *(void *)42;后者是文档扩展名的正确使用方式,对于某些用户来说,原因,你想跳转到地址42。
我已经提交了错误报告 - 该错误报告很快以此错误复制报告,于2007年提交。
I was playing around with labels as values and ended up with this code.
int foo = 0; goto *foo;My C/C++ experience tells me *foo means dereference foo and that this won't compile because foo isn't a pointer. But it does compile. What does this actually do?
gcc (Ubuntu 4.9.2-0ubuntu1~12.04) 4.9.2, if important.
解决方案This is a known bug in gcc.
gcc has a documented extension that permits a statement of the form
goto *ptr;where ptr can be any expression of type void*. As part of this extension, applying a unary && to a label name yields the address of the label, of type void*.
In your example:
int foo = 0; goto *foo;foo clearly is of type int, not of type void*. An int value can be converted to void*, but only with an explicit cast (except in the special case of a null pointer constant, which does not apply here).
The expression *foo by itself is correctly diagnosed as an error. And this:
goto *42;compiles without error (the generated machine code appears to be a jump to address 42, if I'm reading the assembly code correctly).
A quick experiment indicates that gcc generates the same assembly code for
goto *42;as it does for
goto *(void*)42;The latter is a correct use of the documented extension, and it's what you should probably if, for some reason, you want to jump to address 42.
I've submitted a bug report -- which was quickly closed as a duplicate of this bug report, submitted in 2007.
更多推荐
'goto * foo'foo不是指针。这是什么?
发布评论