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

Ð..*_*Ð.. -2 c++ sizeof c++17

考虑以下POD结构:

struct MessageWithArray {
    uint32_t raw;
    uint32_t myArray[10];

    //MessageWithArray() : raw(0), myArray{ 10,20,30,40,50,60,70,80,90,100 } {  };
};
Run Code Online (Sandbox Code Playgroud)

运行以下内容:

#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;
}
Run Code Online (Sandbox Code Playgroud)

给出以下输出:

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
Run Code Online (Sandbox Code Playgroud)

现在,如果我取消注释构造函数(因此它MessageWithArray具有零参数构造函数),则MessageWithArray变为非POD结构.然后我使用构造函数来初始化.这导致代码中的以下更改:

....
struct MessageWithArray {
    .....

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

运行此代码,我得到:

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
Run Code Online (Sandbox Code Playgroud)

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

规格:我在Windows 10计算机上的Visual Studio 2017版本15.7.5,Microsoft Visual C++ 2017中的空项目中运行它.

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

编辑:我决定初始化结构以避免未定义的行为,因为该问题仍然有效初始化.将其初始化为不带10的值会保留我最初观察到的行为,因为数组从未包含任何10的数据(即使它是垃圾,也是随机的).

Hol*_*Cat 8

它与POD-ness无关.

ofstream以文本模式(而不是二进制模式)打开.在Windows上它意味着\n转换为\r\n.

在第二种情况下,结构中恰好有一个0x0A(\n)字节,变为0x0D 0x0A(\r\n).这就是你看到一个额外字节的原因.


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