严格可移植C语言中浮点端点的有效转换

严格可移植C语言中浮点端点的有效转换,c,optimization,floating-point,endianness,C,Optimization,Floating Point,Endianness,使用是好的,因为它是非常可移植的,正确的,并通过编译器设置为严格的,但它的效率比我想要的和可能的低,因为它不使用x86 bswap指令。(可能其他指令集也有类似的高效指令。) 如果我正在运行的系统支持ntohl(),那么我希望ntohl()使用bswap指令并接近我ntohl()做的事情完全正确,但它只在uint32\u t上工作,而不在浮点上工作。uint32_t和float之间的强制转换是类型双关,严格的编译器不允许。使用float和uint32_t进行联合会会遇到未定义的编译器行为(参见前

使用是好的,因为它是非常可移植的,正确的,并通过编译器设置为严格的,但它的效率比我想要的和可能的低,因为它不使用x86 bswap指令。(可能其他指令集也有类似的高效指令。)


如果我正在运行的系统支持
ntohl()
,那么我希望
ntohl()
使用bswap指令并接近我
ntohl()
做的事情完全正确,但它只在uint32\u 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()的环境,但这似乎还没有发生

您的提案第一次违反了“严格的别名规则”
*(uint32\u t*)NetworkOrderFloat
。表达式
(uint32_t*)NetworkOrderFloat
仍然是字符数组的地址,使用类型为
uint32_t
的左值访问它是违反这些规则的。有关详细信息和更多示例,请参见

另一方面,据我所知,C标准并不禁止使用
联合
将浮点表示转换为
uint32\t
。但是,如果您担心会出现这种情况,您可以始终使用
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));

一个像样的现代编译器
memcpy
不调用任何东西,而
ntohl
调用
bswap

“使用浮点数和uint32进行联合会遇到未定义的编译器行为(根据之前的文章),”这不是真的,这是C99TC3中添加的脚注82明确允许的,并在以后的C标准中保留。这当然是实现定义的行为。“使用浮点和uint32_t进行联合运行到未定义的编译器行为(根据前面的文章)对于这里标记的C来说不是问题。以前的帖子是C++的,而联盟是一个问题。当浮点表示不能保证可移植时,什么是严格可移植的?@ yVESDUWST:有一个约束的代码(实现必须使用IEEE-75)比具有两个约束的代码更容易使用。(实现必须使用IEEE-754,并且必须是little endian)。