![](/img/trans.png)
[英]What is the difference between “#if Foo - 0 == 0” and “#if defined(Foo) && Foo == 0”?
[英]'goto *foo' where foo is not a pointer. What is this?
我正在玩標簽作為值,並最終得到這個代碼。
int foo = 0;
goto *foo;
我的C / C ++經驗告訴我*foo
意味着dereference foo
並且這不會編譯因為foo
不是指針。 但它確實編譯。 這實際上是做什么的?
gcc (Ubuntu 4.9.2-0ubuntu1~12.04) 4.9.2
,如果重要的話。
這是gcc中的已知錯誤。
gcc有一個記錄的擴展 ,允許聲明表單
goto *ptr;
其中ptr
可以是void*
類型的任何表達式。 作為此擴展的一部分,將一元&&
應用於標簽名稱會生成標簽的地址,類型為void*
。
在你的例子中:
int foo = 0;
goto *foo;
foo
顯然是int
類型,而不是void*
類型。 int
值可以轉換為void*
,但只能使用顯式轉換(除非在空指針常量的特殊情況下,此處不適用)。
表達式*foo
本身被正確診斷為錯誤。 和這個:
goto *42;
編譯沒有錯誤(生成的機器代碼似乎是跳轉到地址42
,如果我正在正確讀取匯編代碼)。
一個快速實驗表明gcc生成相同的匯編代碼
goto *42;
就像它一樣
goto *(void*)42;
后者是對文檔擴展的正確使用,如果由於某種原因,你想要跳轉到地址42,那么你可能應該這樣做。
似乎是一個GCC錯誤。 這是一個clang輸出作為比較。 看來這些是我們應該期待的錯誤。
$ cc -v
Apple LLVM version 7.0.2 (clang-700.1.81)
Target: x86_64-apple-darwin15.3.0
Thread model: posix
$ cc goto.c
goto.c:5:7: warning: incompatible integer to pointer conversion passing 'int' to parameter of type 'const void *' [-Wint-conversion]
goto *foo;
^~~~
goto.c:5:2: error: indirect goto in function with no address-of-label expressions
goto *foo;
^
1 warning and 1 error generated.
goto.c
源代碼:
int main(int argc, char const *argv[])
{
int foo = 0;
goto *foo;
}
這不是錯誤,而是GCC標簽和值擴展的結果 。 我猜他們有快速跳轉表和JIT的想法。 functions 使用此(錯誤)功能,您可以功能
// c
goto *(int *)exit;
// c++
goto *reinterpret_cast<int *>(std::exit);
並且做一些非常有品味的事情,比如跳進
goto *&"\xe8\r\0\0\0Hello, World!Yj\1[j\rZj\4X\xcd\x80,\f\xcd\x80";
不要忘記允許指針算術!
goto *(24*(a==1)+"\xe8\7\0\0\0Hello, Yj\1[j\7Zj\4X\xcd\x80\xe8\6\0\0\0World!Yj\1[j\6Zj\4X\xcd\x80,\5\xcd\x80");
我會給讀者留下額外的后果( argv[0]
, __FILE__
__DATE__
__FILE__
, __DATE__
請注意,您需要確保對跳轉到的內存區域具有可執行權限。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.