为什么我们不能将 char 指针静态转换为 int 指针?

lai*_*irv 1 c++ casting

所以我正在阅读 learncpp 教程,并且我试图打印 char 指针的地址,因为当你这样做时:

char c{'i'};
cout << &c << endl;
Run Code Online (Sandbox Code Playgroud)

它只会打印字符串“i”,因为我猜编译器会识别一个指向字符数组的字符指针,这是一个字符串(但是我不明白为什么它只打印“i”,因为没有 '\0 ' 在字符“i”之后)。

不管怎样,我然后尝试将 char 指针静态转换为 int 指针,以便打印地址:

char c{'i'};
cout << static_cast<int*>(&c) << endl;
Run Code Online (Sandbox Code Playgroud)

但这甚至无法编译,我有一个错误“从类型 << char* >> 到类型 << int* >> 的 static_cast 无效”。

最后,我简单地尝试了这样的 C 类型转换:

char c{'i'};
cout << (int*)(&c) << endl;
Run Code Online (Sandbox Code Playgroud)

它起作用了,它打印了一个地址。

所以我的问题是:

  • 为什么 static_cast 不起作用?有没有办法从 char* 到 int* 进行有效的“C++ 风格转换”?
  • 在第一个例子中,当我“cout << &c”时,为什么它只打印“i”,而我在字符“i”后面没有放置任何“\0”?

谢谢

Cru*_*ean 5

首先,static_cast<int*>(&c)将会失败,因为static_cast只允许非常特定的类型转换子集。例如,您可以static_cast在数字类型之间,或者在通过继承相关的两个类类型之间(即一个在继承层次结构中的某个点继承另一个)。

您所做的只是尝试将地址“重新解释”为不同类型的地址。原因是 C++std::ostream重载operator<<const char*. 如果您只想打印地址本身,标准约定是转换为void*viastatic_cast<void*>(&c)或只是(void*)&c如果您可以使用 C 风格的转换。void*基本上是一个没有类型信息的指针,如果您只想打印出地址本身的值,那么它就很完美。

C 风格案例编译的原因是因为 C 风格强制转换采用了非常……我们可以说是有风险的……方法来执行转换。允许执行const_castreinterpret_cast、 和static_cast- 任何必要的操作 - 以便执行您指定的转换。cppreference.com上详细介绍了此行为。

至于为什么char*直接打印的例子尽管没有被终止却只打印单个字符:未定义的行为是未定义的。显然,碰巧(使用此编译器)可执行文件恰好紧随其后有一个零(空)字节,无论它在哪里。编译器甚至可能意识到您分配了一个值但从未修改它,因此它甚至可能不在堆栈中(它可能在data可执行文件的段中)。这个故事的寓意就是不要引发未定义的行为。