簡體   English   中英

用C ++命名Mangling

[英]Name Mangling in C++

我正在閱讀這篇文章 - http://www.geeksforgeeks.org/extern-c-in-c/

給出了兩個例子 -

int printf(const char *format,...);

int main()
{
    printf("GeeksforGeeks");
    return 0;
}

它說這不會編譯因為編譯器無法找到'printf'函數的錯位版本。 但是,下面給出輸出。

extern "C"
{
    int printf(const char *format,...);
}

int main()
{
    printf("GeeksforGeeks");
    return 0;
}

這是因為extern“C”阻止名稱被破壞。 但是,代碼運行並提供輸出。 從哪里得到'printf'的定義。 我讀了一篇帖子,默認包含'stdio.h'。 如果是這樣,則必須運行以下代碼。 但是,它給出了未定義printf的錯誤。

int main()
{
    printf("GeeksforGeeks");
    return 0;
}

有人可以解釋一下嗎?

通過將printf專門作為內置處理,您的編譯器非常有用。

示例代碼“tst.cpp”:

int printf(char const *format,...);
int foo(int a, char const *b);

int main() {
    printf("Hello, World!");
    foo(42, static_cast<char const *>("Hello, World!"));
    return 0;
}

使用Microsoft的cl編譯器命令“cl / c tst.cpp”進行編譯時,我們可以檢查生成的.obj並找到:

00000000 r $SG2552
00000010 r $SG2554
00000000 N .debug$S
00000000 i .drectve
00000000 r .rdata
00000000 t .text$mn
         U ?foo@@YAHHPBD@Z
         U ?printf@@YAHPBDZZ
00e1520d a @comp.id
80000191 a @feat.00
00000000 T _main  

請注意,foo()和printf()都被破壞了。

但是當我們通過cygwin“g ++ -c tst.cpp”使用/usr/lib/gcc/i686-pc-cygwin/3.4.4/cc1plus.exe編譯時,我們得到:

00000000 b .bss
00000000 d .data
00000000 r .rdata
00000000 t .text
         U __Z3fooiPKc
         U ___main
         U __alloca
00000000 T _main
         U _printf

這里foo()被破壞而printf()不是,因為cygwin編譯器很有幫助。 大多數人會認為這是編譯器缺陷。 如果使用“g ++ -fno-builtin -c tst.cpp”調用cygwin編譯器,那么問題就會消失,兩個符號都會被破壞。

更新的g ++是正確的,使用/usr/libexec/gcc/i686-redhat-linux/4.8.3/cc1plus通過“g ++ -c tst.cpp”進行編譯得到:

00000000 T main
         U _Z3fooiPKc
         U _Z6printfPKcz

foo()和printf()都被破壞了。

但是如果我們聲明printf使得cygwin g ++無法識別它:

char const * printf(char const *format,...);
int foo(int a, char const *b);

int main() {
    printf("Hello, World!");
    foo(42, static_cast<char const *>("Hello, World!"));
    return 0;
}

然后foo()和printf()都被破壞了:

00000000 b .bss
00000000 d .data
00000000 r .rdata
00000000 t .text
         U __Z3fooiPKc
         U __Z6printfPKcz
         U ___main
         U __alloca
00000000 T _main

我們來看看相關的標准報價:

17.6.2.3鏈接[using.linkage]

2使用外部鏈接聲明的C標准庫中的名稱是否具有extern "C"extern "C++"鏈接是實現定義的。 為此,建議實現使用extern "C++"鏈接。

17.6.4.3保留名稱[reserved.names]

2如果程序在保留它的上下文中聲明或定義名稱,除了本條款明確允許的名稱外,其行為是未定義的。

17.6.4.3.3外部鏈接[extern.names]

1在頭中聲明為具有外部鏈接的對象的每個名稱都保留給實現,以在命名空間std和全局命名空間中指定具有外部鏈接的庫對象。
2在標頭中使用外部鏈接聲明的每個全局函數簽名都保留給實現,以指定具有外部鏈接的函數簽名。
3使用外部鏈接聲明的標准C庫中的每個名稱都保留給實現,以用作名稱空間std和全局名稱空間中具有extern "C"鏈接的名稱。 4使用外部鏈接聲明的標准C庫中的每個函數簽名都保留給實現,以用作具有extern "C"extern "C++"鏈接的函數簽名,或者作為全局命名空間中命名空間范圍的名稱。

我們從中獲得的是編譯器可能會假設任何給定實例中的printf始終引用標准庫函數printf ,因此可以獲取有關它們的任何數量的信息。如果您聲明錯誤,或者確實只是提供自己的,它可以自由地做任何想做的事情,包括但不限於神奇地糾正它。
無論如何,你無法知道它所期望的語言聯系。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM