转换基元时的内存解释
Memory interpretation while casting primitives
在像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。我是幸运还是错过了一些基本的东西?
C 中的强制转换不会重新解释任何东西。它们是价值转换。 (int)c
的意思是取c
的值并将其转换为int
,这基本上在所有系统上都是无操作的。(它不能成为无操作的唯一方法是如果char
的范围大于int
的范围,例如,如果char
和int
都是32位的,但char
是无符号的。
如果要重新解释值背后的表示形式(位模式),则该值必须首先作为对象(左值)存在,而不仅仅是表达式的值(通常称为"rvalue",尽管这种语言在 C 标准中未使用)。然后,您可以执行以下操作:
*(new_type *)&object;
但是,除非new_type
是字符类型,否则这会通过违反别名规则来调用未定义的行为。C++有一种"重新解释强制转换"来做到这一点,大概可以避免违反混叠规则,但由于我不熟悉C++,我无法为您提供有关它的好细节。
在C++示例中,获得不同结果的原因是运算符重载。 (int)'A'
不会更改值或其解释方式;相反,具有不同类型的表达式会导致调用operator<<
函数的不同重载。另一方面,在 C 中,(int)'A'
始终是无操作的,因为'A'
在 C 中具有以类型 int
开头。
我是幸运还是错过了一些基本的东西?
是的,您缺少一些基本的东西:编译器不会从内存中读取char
,就好像内存表示int
一样。相反,它将char
读取为 char,然后对值进行符号扩展以适应int
,因此char
-1
也变得int
-1
。符号扩展意味着在要扩展的最有效字节的左侧添加 1
s 或 0
s,具体取决于该数字的符号位。无符号类型始终用零*填充。
符号扩展通常通过执行专用的硬件指令在寄存器中完成,因此运行速度非常快。
*正如 Eric Postpischil 在评论中指出的那样,
char
类型可能是有符号的,也可以是无符号的,具体取决于 C 实现。
当你分配一个字符时,没有东西在左边或右边。这是八位,仅此而已。因此,当您将 8 位值转换为 32 位时,您仍然得到 65:
0100.0001
到0000.0000 0000.0000 0000.0000 0100.0001
魔法,没有运气。
在你的代码中,"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 将合并来自 mem 地址 0x02 和 0x03 的值。
嗯,问题是,此行为可能会根据您编译的平台和您使用的编译器而改变。
ISO 标准将 (int) 定义为铸件。在这种情况下,编译器将解释 (int)c,如 static_cast(c)//在 c++ 中
现在,你很幸运,你的编译器将 (int) 解释为一个简单的强制转换。这是任何 c/c++ 编译器的常见行为,但可能存在一些邪恶的、无名的 c++ 编译器,它们会对该编译器进行重新解释,最终导致不可预测的结果(取决于平台)。
这就是为什么你应该使用static_cast(c)是100%舒尔如果你想重新解释它,当然reinterpret_cast(c)
但是,同样,它通常是 C 样式的强制转换,因此 C 将被转换为整数。
- 将字符串存储在c++中的稳定内存中
- 请解释"函数1(p1,p2,p3);"的输出
- 我在 2D 数组的动态内存分配中遇到了一些奇怪的代码C++? 请解释一下这是什么?
- 在内存级别重新解释向量的字节
- std::future::wait 是内存障碍吗?(我无法解释这种数据竞赛)
- Marshal.StructureToPtr出现无法解释的内存泄漏
- 转换基元时的内存解释
- 分配内存并使用 new in C++重新解释指针
- 重新解释cast<是否安全;bool*>清空内存
- C++ Visual Studio - 在简单示例中解释内存泄漏检测
- 如何在内存中解释这些位
- 对C++11内存模型有什么好的解释
- 解释Valgrind内存泄漏总结日志
- 对指向固定大小数组的指针数组的内存分配的解释
- 我可以将键值对的内存映射文件重新解释为映射以便对它们进行排序吗?
- C#中引用类型的内存方面的显式强制转换解释
- 在c++中读取和解释内存页面文件
- 为什么在同一x64机器的2个不同项目上对内存的解释不同?这是Endianness吗?
- 解释DrMemory日志,内存泄漏
- c++内存泄漏解释分析