所以,我知道stdint.h
标头中的类型提供了标准化的宽度整数类型,但是我想知道用什么类型或方法来保证double
或其他浮点的大小跨平台类型?具体来说,这将处理void*
#include <stdio.h>
#include <stdlib.h>
void write_double(void* buf, double num)
{
*(double*)buf = num;
}
double read_double(void* buf)
{
return *(double*)buf;
}
int main(void) {
void* buffer = malloc(sizeof(double));
write_double(buffer, 55);
printf("The double is %f\n", read_double(buffer));
return 0;
}
在上面的程序中说,如果我将void*
写入文件或者是否在另一个系统上使用,是否会有一些标准方法来保证浮点类型的大小或双倍?
答案 0 :(得分:5)
如何保证C中双精确的大小?
使用_Static_assert()
#include <limits.h>
int main(void) {
_Static_assert(sizeof (double)*CHAR_BIT == 64, "Unexpected double size");
return 0;
}
自C11以来 _Static_assert
可用。否则代码可以使用运行时断言。
#include <assert.h>
#include <limits.h>
int main(void) {
assert(sizeof (double)*CHAR_BIT == 64);
return 0;
}
虽然这可以确保double
的大小为64,但并不能确保IEEE 754 double-precision binary floating-point format遵守。
代码可以使用__STDC_IEC_559__
定义
__STDC_IEC_559__
的实现应符合本附件中的规范.C11附件F IEC 60559浮点运算
然而,这可能过于严格。许多实现都遵循大部分标准,但仍然没有设置宏。
是否有一些标准方法可以保证浮点类型的大小或双倍?
最好的保证是将FP值写为十六进制表示或具有足够十进制数的指数。见Printf width specifier to maintain precision of floating-point value
答案 1 :(得分:3)
浮点类型的问题是C标准没有指定它们应该如何表示。不需要使用IEEE 754 。
如果您在使用IEEE 754的系统和不使用IEEE 754的系统之间进行通信,即使大小相同,您也无法在一个系统上进行通信而在另一个系统上进行通信。
您需要以已知格式序列化数据。您可以使用LightGBM
将其转换为文本格式,也可以进行一些数学计算以确定基数和尾数并存储它们。
答案 2 :(得分:1)
浮点值在IEEE标准浮点运算(IEEE 754)中定义,并具有标准尺寸:
float
,完整"single precision floating point number":32位double
,完整"double precision floating point number":64位还存在以下内容:
此格式在C11标准,附件F&#34; IEC 60559浮点运算&#34;中重复使用。 ISO / IEC 9899:2011(en)。
答案 3 :(得分:0)
为什么在运行时使用CHAR_BIT
并断言?我们可以在编译时这样做。
void write_double(void* buf, double num)
{
char checkdoublesize[(sizeof(double) == 8)?1:-1];
*(double*)buf = num;
}
您的代码仍未定义,因为它不保证IEEE或字节序,但它会捕获一个糟糕的双倍大小。如果你的平台足够新用于htonq,这将允许字节序工作
void write_double(void* buf, double num)
{
char checkdoublesize[(sizeof(double) == 8)?1:-1];
*(int64_t*)buf = htonq(*(volatile int64_t*)&num);
}
double read_double(void* buf)
{
int64_t n = ntohq(*(int64_t*)buf);
return *(volatile double*)&n;
}
其中volatile
只是告诉编译器的最短路径,实际上定义了指针强制转换。通常它无论如何都是正确的,但在N
内联级别之后可能不会再这样了。