2010-12-16 49 views
34

爲什麼當我運行這個main.cpp爲什麼typeid.name()使用GCC返回奇怪的字符,以及如何讓它打印未加密的名字?

#include <iostream> 
#include <typeinfo> 

using namespace std; 

struct Blah {}; 

int main() { 
    cout << typeid(Blah).name() << endl; 
    return 0; 
} 

通過與GCC 4.4.4版本編譯它:

g++ main.cpp 

我得到這個:

4Blah 

基於Visual C++ 2008,我會得到:

struct Blah 

有沒有辦法讓它只是打印Blahstruct Blah

+0

[C++中打印變量類型]的可能重複(http://stackoverflow.com/questions/81870/print-variable-type-in​​-c) – 2015-06-18 15:13:03

+1

[Unmangling std :: type \ _info :: name](http://stackoverflow.com/questions/281818/unmangling-the-result-of-stdtype-in​​foname) – bain 2016-11-20 23:54:35

回答

52

name的返回值是實現定義的:實現甚至不需要爲不同類型返回不同的字符串。

從g ++得到的是decorated name,您可以使用c++filt命令或__cxa_demangle「去鑲嵌」。

+13

特別是'C++ filt -t' – 2015-01-16 13:09:58

+1

唉,該死的GCC – metamorphosis 2016-04-02 04:57:40

3

typeid().name()是依賴於實現的。它甚至可以爲每種類型返回空字符串。這不是非常有用的實現,但它是有效的。

+0

不。它可能不會爲每個類型返回空字符串。字符串表示的方式是應用程序定義的,但根據C++標準,它必須與其他類型不同。空弦你不能這樣做。 – 2017-03-03 17:35:30

11

有沒有辦法讓它只是打印

Blahstruct Blah

std::typeinfo::name()的結果未指定。它甚至可能爲所有類型返回相同的字符串(實際上,對於所有類型而言,實際上是空字符串),並且實現仍然符合標準。你不能依靠它的結果。真的,我發現它唯一有用的是調試。

告訴我們你需要什麼。性格常常是你用來代替的。

+0

在我的程序中,我只想將我的結構名稱記錄到日誌文件中。按照上面的例子,我可以輸入如下內容:'LOG(「Blah」);'。但是我想考慮將來可能會改變結構體的名稱,所以我試着去做:'LOG(typeinfo(Blah).name();' – sivabudh 2010-12-16 22:24:26

+1

@ ShaChris23:好的,我想你會有並不是所有的編譯器都以相同的方式進行編譯,但是,看看運行時庫發出的是什麼,而不是'blah',你有一個字符串映射到字符串列表的向量,這很容易超過對於日誌文件大小有任何明顯的限制 – sbi 2010-12-17 08:35:46

16

返回的字符串是實現定義的。

gcc正在做的是返回損壞的名稱。
您可以將重整名稱轉換爲純文本使用C++ filt的

> a.out | c++filt 
+0

下面是一個例子:假設stdout的內容是'PFPFiiEiiE',我們可以使用shell命令'echo' PFPFiiEiiE「| C++ filt',結果是'int(*(*)(int,int))(int)'。 – Hustlion 2017-09-02 11:05:46

6

正如其他人所說,這裏的結果實現定義,這意味着執行(即,編譯器工具鏈)是可以自由地定義它的想法,只要它在某個地方記錄下來。

從C++標準,部分18.5.1/1 [lib.type.info]:

type_info描述鍵入由實現產生的信息。 這個類的對象有效地存儲了一個指向該類型名稱的指針,以及一個適合於比較兩種類型的編碼值,用於相等或整理順序。類型的名稱,編碼規則和整理順序全部未指定 ,程序之間可能會有所不同。

2

in 4Blah,4是你班上的字母數。例如,如果你的類名是myEmptyClass,那麼它會打印12myEmptyClass。