【问题标题】:How to Identify type of a variable如何识别变量的类型
【发布时间】:2016-08-25 05:13:07
【问题描述】:

如何正确识别 c++ 中的变量类型。我试过这个来识别一种变量:

int a = 5;
std::cout << typeid(a).name() << std::endl;

而不是预期的输出 int,它给你:

i

我很困惑为什么会这样。它以某种方式只给你你声明变量的类型的第一个字母。 Int 不是唯一的......还有这个:

 char a = 'A'
 std::cout << typeid(a).name() << std::endl;

Example Program

有一个简单的解决方法吗?任何帮助将不胜感激!

【问题讨论】:

  • 您似乎在混淆“识别”和“生成 C++ 源代码”...?识别只是意味着您可以将一些独特的特征分配给您以后可以用于查找和比较的东西。通常,C++ 中没有任何工具可以创建某种语言结构的源代码级字符串表示。

标签: c++ types typeid gettype


【解决方案1】:

我的意思是即使它是不可理解的。例如,如果 int 是 32432423423403095590353095309530953,那么它总是相同的。所以我可以很容易地设置一个函数来返回变量是什么类型...

你得到的结果已经实现了。也许它有助于解释您使用的 C++ 实现如何准确地获取您所看到的字符串。

g++ 实现 typeid(...).name() 以便它返回类型的“ABI mangled”名称。这是在编译的目标文件和库中使用的一种表示类型的特殊方式。如果您将 C++ 代码编译成程序集,您将看到“符号”,这些“符号”标识生成的汇编代码与哪些函数或数据相关。例如取函数:

int foo(double a, char b) {
    return a + b;
}

compile it to assembly,您会看到类似以下内容:

_Z3foodc:
.LFB0:
    .cfi_startproc
    movsbl  %dil, %edi
    cvtsi2sd    %edi, %xmm1
    addsd   %xmm1, %xmm0
    cvttsd2si   %xmm0, %eax
    ret
    .cfi_endproc

这里的第一行是用于标识函数int foo(double,char) 的'mangled' 符号。它包含代表函数名称的“Z3foo”,然后是代表第一个参数类型的“d”和代表第二个参数类型的“c”。该符号用于标识二进制对象文件中的函数、库索引中的函数、想要链接到该函数的其他编译对象等。

您也可以使用 c++filt 工具demangle symbols。该工具会扫描您传递给它的任何文本,以寻找符合修饰语法的内容,并将它们转换为更像这些类型在 C++ 源代码中的命名方式。

g++ 实现了Itanium C++ ABI 修改方案。大多数 unix 平台编译器都使用它。

那么,回到你的代码,猜猜这些符号中“int”类型是如何表示的。

Itanium ABI specifies 一个额外的去杂化功能。 Here's 一个使用它的例子。

【讨论】:

  • 感谢您提供库!还要感谢您向我展示可怕的汇编代码......:P(OfCourse 3 行 C++ 代码 = 10 行汇编代码 xD)
【解决方案2】:

你的代码有两个问题,

首先typeid(..).name()返回一个实现定义的字符串,它可以是任何有效的字符串,它可以为每个类型返回"",它甚至可以为每个程序执行返回不同的值(虽然我相信这个值不能改变执行期间)。 GCC(和 Clang?)返回不可读的名称,而 Visual C++ 返回合理的名称(在本例中为 int

其次,如果a的类型是多态类型,typeid(a)将返回typeid对应于a的动态类型而不是用于声明a的类型,而是使用@ 987654332@.

不幸的是,没有标准的方法可以以人类可读或正确的 C++ 语法的方式获取类型的名称。 (如果您想要一种适用于 GCC 的方式,请参阅 Unmangling the result of std::type_info::name

编辑使用 Boost,您可以尝试 std::cout &lt;&lt; boost::typeindex::type_id&lt;decltype(a)&gt;().pretty_name() &lt;&lt; std::endl;,请参阅 Getting human readable and mangled type names

【讨论】:

  • typeid 在非多态类型上很好 - 它只是为您提供有关静态类型的信息,而不评估表达式。参见例如en.cppreference.com/w/cpp/language/typeid.
  • 所以在c++中不能获取变量的类型??
  • @Dsafds 可以,decltype(a) 获取类型,您可以使用 decltype(typeid(a)).name() 获取类型的“名称”,但没有可移植的方式来获取任何有意义/可理解的名称,抱歉?。
  • 当我这样做时@Isaac 它给了我错误:main.cpp: In function 'int main()': main.cpp:10:22: error: expected unqualified-id before 'decltype' std::cout
  • @Dsafds 是我的错误,我的意思是typeid(decltype(a)),还有typeiddecltype 是关键字,而不是std 命名空间的成员(即你不能在之前使用:: 运算符它们)不必相同,如果您只想获取标识类型的运行时对象,请使用typeid(返回的值必须是唯一的,但typeid(..).name()的值不必是)
【解决方案3】:

类型名称不应该是您所期望的。有关获取实际类型名称的方法,请参阅 this answer。注意 - 它仅适用于 gcc 和一些 additional installation,适用于 clang。

使用 Visual C++,您应该调用 UnDecorateSymbolName,但显然是 ints are called int there

【讨论】:

  • msdn.microsoft.com/en-us/library/bb384066.aspx”和什么有什么关系?其次,对于 Visual C++(至少我的版本,14.0.23918),返回的名称是有效的 C++ 语法,并且是您所期望的,例如typeid(decltype(std::cout)).name() 返回class std::basic_ostream&lt;char,struct std::char_traits&lt;char&gt; &gt;
猜你喜欢
  • 1970-01-01
  • 2015-10-23
  • 2022-01-26
  • 2021-09-27
  • 1970-01-01
  • 2014-06-18
  • 2017-02-02
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多