c++ - 为什么要转换为指针然后取消引用?

标签 c++ c casting

我正在浏览这个示例,该示例具有输出十六进制位模式以表示任意 float 的函数。

void ExamineFloat(float fValue)
{
    printf("%08lx\n", *(unsigned long *)&fValue);
}

为什么取fValue的地址,转换成无符号长指针,然后解引用?所有这些工作不都等同于直接转换为 unsigned long 吗?

printf("%08lx\n", (unsigned long)fValue);

我试过了,答案不一样,很困惑。

最佳答案

(unsigned long)fValue

根据“通常的算术转换”,这会将 float 值转换为 unsigned long 值。

*(unsigned long *)&fValue

这里的意图是取fValue存储的地址,假装没有float而是unsigned long这个地址,然后读取那个 unsigned long。目的是检查用于在内存中存储 float 的位模式。

如图所示,这会导致未定义的行为。

原因:您不能通过指向与对象类型不“兼容”的类型的指针来访问对象。 “兼容”类型例如是 (unsigned) char 和所有其他类型,或共享相同初始成员的结构(这里说的是 C)。见§6.5/7 N1570对于详细的 (C11) 列表(请注意,我对“兼容”的使用与引用文本中的不同 - 更广泛。)

解决方案:转换为 unsigned char *,访问对象的各个字节并从中组装出 unsigned long:

unsigned long pattern = 0;
unsigned char * access = (unsigned char *)&fValue;
for (size_t i = 0; i < sizeof(float); ++i) {
  pattern |= *access;
  pattern <<= CHAR_BIT;
  ++access;
}

请注意(正如@CodesInChaos 指出的那样)上面将浮点值视为首先存储其最高有效字节(“big endian”)。如果您的系统对浮点值使用不同的字节顺序,您需要进行调整(或重新排列上述 unsigned long 的字节,对您来说更实用)。

关于c++ - 为什么要转换为指针然后取消引用?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39312058/

相关文章:

当我尝试将指针数组复制到设备时出现 cudaMalloc 错误

java - java中的动态方法调度

c++ - 抽象具有不同返回类型的成员函数

c++ - ICP的保证,内部指标

c++ - 需要左值作为赋值的左操作数 - LOBYTE/HIBYTE

c 访问不同翻译单元中的数据成员

c++ - 无法编译简单的 C++ 程序

c - 我们如何检查输入字符串是否是有效的 double 值?

java - 如何将地理点经度+纬度转换为两倍?

java - 为什么 Java 需要显式向下转型?