C++ 序列化,不带库的整数,得到奇怪的结果
我有一个整数,我想把它序列化成二进制文件。我不在乎跨平台 我正在做以下工作:C++ 序列化,不带库的整数,得到奇怪的结果,c++,C++,我有一个整数,我想把它序列化成二进制文件。我不在乎跨平台 我正在做以下工作: std::ofstream f; f.open(path, std::ios::binary); int n = 200; f.write((char*)&n, sizeof(int)); f.close() 然后,在使用ifstream再次打开文件并将其所有内容读入字符向量后,我执行以下操作以获取整数: char* ptr = avector.data(); int n = *ptr; ptr += siz
std::ofstream f;
f.open(path, std::ios::binary);
int n = 200;
f.write((char*)&n, sizeof(int));
f.close()
然后,在使用ifstream再次打开文件并将其所有内容读入字符向量后,我执行以下操作以获取整数:
char* ptr = avector.data();
int n = *ptr;
ptr += sizeof(int);
这似乎只有在n 127(如本例中的“n”)得到一个奇怪的值而不是200时才起作用。在此代码中:
char* ptr = avector.data();
int n = *ptr;
您正在将一个字节转换为int
取消引用char
指针。您需要的是复制数据:
char* ptr = avector.data();
int n = 0;
memcpy( &n, ptr, sizeof(n) );
或:
您应该知道,这不是可移植的解决方案
你不能做的是:
虽然它看起来很合理,而且可以编译,但实际上非常流行,甚至看起来可以工作,但它违反了一种称为严格别名规则的规则。您可以将对象视为char[]
,但不能反过来看。无论是否可移植,此处都需要副本。在此代码中:
char* ptr = avector.data();
int n = *ptr;
您正在将一个字节转换为int
取消引用char
指针。您需要的是复制数据:
char* ptr = avector.data();
int n = 0;
memcpy( &n, ptr, sizeof(n) );
或:
您应该知道,这不是可移植的解决方案
你不能做的是:
虽然它看起来很合理,而且可以编译,但实际上非常流行,甚至看起来可以工作,但它违反了一种称为严格别名规则的规则。您可以将对象视为
char[]
,但不能反过来看。无论是否可移植,此处都需要副本。*ptr
仅在ptr
是指向char的指针时才会产生(-128,+127)的结果。您可以将任何对象视为char
的数组,但反之则不正确。因为您不关心代码是否跨平台,请在其他平台上尝试。也许你会找到一个有用的。@DavidSchwartz像个老克雷?@user4581301正是。不可否认的是,这些代码可以在某些平台上工作,而不能在其他平台上工作。在本例中,它适用于n*ptr
仅当ptr
是指向char的指针时,才会产生(-128,+127)的结果。您可以将任何对象视为char
的数组,但反之则不正确。因为您不关心代码是否跨平台,请在其他平台上尝试。也许你会找到一个有用的。@DavidSchwartz像个老克雷?@user4581301正是。不可否认的是,这些代码可以在某些平台上工作,而不能在其他平台上工作。在本例中,它适用于n@kerrytazi可能有效,但违反了严格的别名,因此无法定义行为。@kerrytazi可能允许您将任何内容视为字节,而不允许您将字节视为其他内容。在这种情况下,您必须memcpy
。@DavidSchwartz没关系,演员阵容违反了严格的别名,句号。这里需要一份副本。(很多程序员都弄错了。)std::copy
比memcpy
要好。@SergeyA Troll:P@SergeyA如果我错了,请纠正我,但如果没有强制转换,该向量必须包含char
,否则无法从data()
初始化char*
?@kerrytazi可能会工作,但是违反了严格的别名,所以没有定义行为。@kerrytazi可能允许您以字节的形式查看任何内容,但不允许您以其他方式查看字节。在这种情况下,您必须memcpy
。@DavidSchwartz没关系,演员阵容违反了严格的别名,句号。这里需要一份副本。(很多程序员都弄错了。)std::copy
比memcpy
要好。@SergeyA Troll:P@SergeyA如果我错了,请纠正我,但如果没有强制转换,该向量必须包含char
,否则无法从其数据()初始化char*
?