使用this answer是好的,因为它非常便携,正确并且将编译器设置为严格,但它的效率低于我想要的效果,因为它不使用x86 bswap指令。 (也许其他指令集具有类似的有效指令。)
如果我正在运行的系统支持ntohl()
,那么我希望ntohl()
能够使用bswap指令并让我接近。 ntohl()
完全正确,但它只适用于uint32_t,而不适用于浮点数。 uint32_t和float之间的转换是类型惩罚,严格的编译器不允许。使用float和uint32_t建立联合会遇到未定义的编译器行为(以前的帖子)。
我之前的帖子中的理解是明确允许从任何指针类型转换为char *,反之亦然。那么这个解决方案有什么问题呢?我还没有在任何答案中看到它。
char NetworkOrderFloat[4]; // Assume it contains network-order float bytes
uint32_t HostOrderInt = ntohl(*(uint32_t *)NetworkOrderFloat);
char *Pointer = (char *)&HostOrderInt;
float HostOrderFloat = *(float *)Pointer;
这里理想的解决方案似乎是支持ntohf()的更多环境,但这似乎还没有发生。
答案 0 :(得分:3)
您的提案违反了“严格的别名规则”,这是*(uint32_t *)NetworkOrderFloat
的第一次。表达式(uint32_t *)NetworkOrderFloat
仍然是字符数组的地址,并且使用类型为uint32_t
的左值访问它是违反这些规则的。可以在this article中找到详细信息和更多示例。
另一方面,使用union
将浮点表示转换为uint32_t
,据我所知,C标准并未禁止。但是如果您担心它,可以随时使用memcpy
。
float NetworkOrderFloat = ...;
uint32_t tmp;
_Static_assert(sizeof(uint32_t)==sizeof(float),"unsupported arch");
memcpy(&tmp, &NetworkOrderFloat, sizeof(float));
tmp = ntohl(tmp);
memcpy(&HostOrderFloat, &tmp, sizeof(float));
一个不错的现代编译器should compile memcpy
调用任何内容,ntohl
调用bswap
。