Рассмотрим следующую структуру 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
Теперь, я не очень интересуюсь фактическими шестнадцатеричными значениями, что мне интересно почему в дампе структуры без POD есть еще один байт по сравнению с дампом структуры POD, когда sizeof () объявляет, что они имеют одинаковое количество байтов? Возможно ли, что, поскольку конструктор делает структуру не POD, что-то скрытое было добавлено в структуру? sizeof () должна быть точной проверкой во время компиляции, правильно? Возможно ли что-то избежать измерения с помощью sizeof ()?
Характеристики: Я запускаю это в пустом проекте в Visual Studio 2017 версии 15.7.5, Microsoft Visual C ++ 2017, на компьютере с Windows 10.
Процессор Intel Core i7-4600M
64-разрядная операционная система, 64-разрядный процессор
РЕДАКТИРОВАТЬЯ решил инициализировать структуру, чтобы избежать неопределенного поведения, и потому что вопрос все еще актуален при инициализации. Инициализация его значением без 10 сохраняет поведение, которое я наблюдал вначале, потому что данные в массиве никогда не содержали никаких десятков (даже если это были мусорные и случайные).
Это не имеет ничего общего с ПОД.
Ваш ofstream
открывается в текстовом режиме (а не в двоичном режиме). На окнах это означает, что \n
превращается в \r\n
,
Во втором случае оказался один 0x0A
(\n
байт в структуре, которая стала 0x0D 0x0A
(\r\n
). Вот почему вы видите дополнительный байт.
Кроме того, использование неинициализированных переменных в первом случае приводит к неопределенному поведению, которое в этом случае не проявилось.
Другой ответ объясняет проблему с записью двоичных данных в поток, открытый в текстовом режиме, однако этот код в корне неверен. Нет необходимости что-либо сбрасывать, можно использовать правильный способ проверить размеры этих структур и убедиться, что они равны 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));