这些结构在文件中的大小不同,但在程序内存中的大小相同

The size of these structs are different in a file but the same in program memory

本文关键字:程序 内存 结构 文件      更新时间:2023-10-16

考虑以下POD结构:

struct MessageWithArray {
uint32_t raw;
uint32_t myArray[10];
//MessageWithArray() : raw(0), myArray{ 10,20,30,40,50,60,70,80,90,100 } {  };
};

运行以下内容:

#include <type_traits>
#include <iostream>
#include <fstream>
#include <string>
struct MessageWithArray {
uint32_t raw;
uint32_t myArray[10];
//MessageWithArray() : raw(0), myArray{ 10,20,30,40,50,60,70,80,90,100 } {  };
};
//https://stackoverflow.com/questions/46108877/exact-definition-of-as-bytes-function
template <class T>
char* as_bytes(T& x) {
return &reinterpret_cast<char&>(x);
// or:
// return reinterpret_cast<char*>(std::addressof(x));
}
int main() {
MessageWithArray msg = { 0, {0,1,2,3,4,5,6,7,8,9} };
std::cout << "Size of MessageWithArray struct: " << sizeof(msg) << std::endl;
std::cout << "Is a POD? " << std::is_pod<MessageWithArray>() << std::endl;
std::ofstream buffer("message.txt");
buffer.write(as_bytes(msg), sizeof(msg));
return 0;
}

给出以下输出:

MessageWithArray结构体的大小:44

是POD吗?1

"message.txt"文件的十六进制转储如下所示:

00  00  00  00  00  00  00  00  01  00  00  00  02  00  00  00
03  00  00  00  04  00  00  00  05  00  00  00  06  00  00  00
07  00  00  00  08  00  00  00  09  00  00  00

现在,如果我取消对构造函数的注释(这样MessageWithArray就有了一个零参数构造函数(,MessageWithArray就会变成一个非POD结构。然后我使用构造函数进行初始化。这导致代码发生以下变化:

....
struct MessageWithArray {
.....
MessageWithArray() : raw(0), myArray{ 10,20,30,40,50,60,70,80,90,100 }{  };
};
....
int main(){
MessageWithArray msg;
....
}

运行此代码,我得到:

MessageWithArray结构体的大小:44

是POD吗?0

"message.txt"文件的十六进制转储如下所示:

00  00  00  00  0D  0A  00  00  00  14  00  00  00  1E  00  00
00  28  00  00  00  32  00  00  00  3C  00  00  00  46  00  00
00  50  00  00  00  5A  00  00  00  64  00  00  00

现在,我对实际的十六进制值不太感兴趣,我好奇的是当sizeof((声明它们是相同数量的字节时,为什么非POD结构转储中比POD结构转储多了一个字节?有没有可能,因为构造函数使结构成为非POD,所以隐藏的东西被添加到了结构中?sizeof((应该是一个准确的编译时检查,对吗?有什么东西可能避免用sizeof((来衡量吗?

规范:我在Windows 10计算机上的Visual Studio 2017 15.7.5版本Microsoft Visual C++2017中的一个空项目中运行此规范。

英特尔酷睿i7-4600M CPU64位操作系统,基于x64的处理器

EDIT:我决定初始化结构以避免"未定义的行为",因为这个问题在初始化时仍然有效。将其初始化为不含10的值可以保留我最初观察到的行为,因为数组中的数据从未包含任何10(即使它是垃圾和随机的(。

它与POD无关。

您的ofstream是以文本模式(而不是二进制模式(打开的。在windows中,这意味着n被转换为rn

在第二种情况下,结构中恰好有一个0x0A(n(字节,即0x0D 0x0A(rn(。这就是为什么你会看到一个额外的字节。


此外,在第一种情况下使用未初始化的变量会导致未定义的行为,也就是说,这种情况本身并没有表现出来。

其他答案解释了将二进制数据写入以文本模式打开的流中的问题,但这段代码根本错误。不需要转储任何东西,检查这些结构的大小并验证它们是否相等的正确方法是使用static_assert:

struct MessageWithArray {
uint32_t raw;
uint32_t myArray[10];
};
struct NonPodMessageWithArray {
uint32_t raw;
uint32_t myArray[10];
NonPodMessageWithArray() : raw(0), myArray{ 10,20,30,40,50,60,70,80,90,100 } {}
};
static_assert(sizeof(MessageWithArray) == sizeof(NonPodMessageWithArray));

在线编译器