1

在像 C/C++ 这样的语言中,当我们这样做时:

char c = 'A';

我们分配内存以二进制形式存储数字 65:

stuff_to_the_left_01000001_stuff_to_the_right

那么如果我们这样做:

int i = (int) c;

据我了解,我们是在对编译器说,它应该将布局为 的位模式解释为stuff_to_the_left_01000001__00000000_00000000_00000000_stuff_to_the_right,这可能是也可能不是 65。

当我们在操作期间执行强制转换时也会发生同样的情况

cout << (int) c << endl;

在上述所有内容中,我得到了字符的“A”和十进制的 65。我是幸运还是我错过了一些基本的东西?

4

5 回答 5

2

C 中的强制转换不会重新解释任何内容。它们是价值转换。(int)c表示取 的值c并将其转换为int,这在基本上所有系统上都是无操作的。(它可能无法成为空操作的唯一方法是,如果 的范围char大于 的范围int,例如,如果charint都是 32 位但char没有符号。)

如果您想重新解释一个值的表示(位模式),该值必须首先作为一个对象(左值)存在,而不仅仅是一个表达式的值(通常称为“右值”,尽管这种语言在 C 标准中不使用) )。然后您可以执行以下操作:

*(new_type *)&object;

但是,除了new_type字符类型的情况外,这会通过违反别名规则来调用未定义的行为。C++ 有一种“重新解释演员表”可以做到这一点,这大概可以避免破坏别名规则,但由于我不熟悉 C++,我无法为您提供有关它的详细信息。

在您的 C++ 示例中,您得到不同结果的原因是运算符重载。(int)'A'不会改变值或它的解释方式;相反,具有不同类型的表达式会导致operator<<要调用的函数的不同重载。另一方面,在 C 中,(int)'A'始终是空操作,因为在 C 中具有以开头的'A'类型。int

于 2012-08-11T02:37:28.673 回答
2

我是幸运还是我错过了一些基本的东西?

是的,您缺少一些基本的东西:编译器不会char从内存中读取 ,就好像内存表示int. 相反,它将 a 读取char为 char,然后对该值进行符号扩展以适合 a ,int因此也一样。符号扩展意味着在要扩展的最高有效字节的左侧添加s 或s,具体取决于该数字的符号位。无符号类型总是用零填充*char -1int -110

符号扩展通常通过执行专用硬件指令在寄存器中完成,因此运行速度非常快。


*正如Eric Postpischil在评论中指出的那样,char类型可能是有符号或无符号的,具体取决于 C 实现。

于 2012-08-11T02:40:56.263 回答
0

当你分配一个字符时,左边或右边没有东西。它是八位,仅此而已。因此,当您将 8 位值转换为 32 位时,您仍然会得到 65:

0100.00010000.0000 0000.0000 0000.0000 0100.0001

没有魔法,就没有运气。

于 2012-08-11T02:40:33.057 回答
0

在您的代码中,“i”有自己的地址,“c”有自己的地址。值正在从 c“复制”到 i。至于“(int) c”,同样如此。尽管编译器为我们做了这些,如下所示。

     |--- i ---|- c-|  
 0x01 0x02 0x03 0x04
+--------------------......
| 00 | 00 | 08 | 08 |......  
+--------------------......

如果这是基于指针的分配,您将是正确的。

例如

 0x01 0x02 0x03
+---------------......
| 07 | 10 | 08 |......
+---------------......
int *p;
char c = 10;
p = &c;
print(*p); //not a real method just something that can print.

这里 *p 将具有来自内存地址 0x02 和 0x03 的组合值。

于 2012-08-11T02:48:39.037 回答
-1

好吧,问题是,这种行为可能会根据您正在编译的平台和您正在使用的编译器而改变。

ISO 标准将 (int) 定义为强制转换。在这种情况下,您的编译器将像 static_cast(c) //in c++ 一样解释 (int)c

现在,您很幸运,您的编译器将 (int) 解释为简单的强制转换。这是任何 c/c++ 编译器的常见行为,但可能存在一些邪恶的、无名的 c++ 编译器,它们会对那个编译器进行重新解释,最终导致不可预测的结果(取决于平台)。

这就是为什么你应该使用 static_cast(c) 来 100% 舒尔,如果你想重新解释它,当然是 reinterpret_cast(c)

但是,同样,它通常是 c 风格的强制转换,因此 c 将被强制转换为整数。

于 2012-08-11T02:46:15.513 回答