sizeof () часть структуры C - вроде

Я хочу захватить часть данных внутри некоторых структур C, чтобы частично сериализовать / десериализовать их, записать байты из памяти на диск и наоборот.

Структуры заранее не известны, они динамически построены с помощью моего собственного генератора кода C (а также кода, который его сериализует). Сериализуемые поля будут помещены в начало структуры.

Допустим, у a есть структура с 4 полями, и первые два должны быть сериализованы:

typedef struct {
   int8_t x1;   
   int32_t x2;   /* 1 + 4  = 5 bytes (if packed) */
   int8_t y1;
   int32_t  y2;   /* 1 + 4  +1 + 4 = 10 bytes (if packed) */ 
}  st;

Я планирую захватить указатель на переменную структуры и написать / читать n байтов, которые покрывают эти два первых поля ( x1, x2 ). Я не думаю, что мне нужно беспокоиться о выравнивании / упаковке, потому что я не предполагаю, что сериализация выдержит различные компиляции (ожидается, что только уникальный исполняемый файл будет читать / записывать данные). И, поскольку я нацелен на широкий круг архитектур компиляторов, я не хочу делать предположения относительно упаковки выравнивания или специфических уловок компилятора.

Затем мне нужно подсчитать байты. И я могу' Просто сделайте sizeof (st.x1) + sizeof (st.x2) из-за alingment-padding. Итак, я планирую вычесть указатели от начала структуры до первого «непостоянного» поля:

st myst;
int partsize = (char*)&myst.y1 - (char*)(&myst);
printf("partial size=%d (total size=%d)\n",partsize,sizeof(myst));  

Кажется, это работает. И это может быть помещено в макрос.

(Для записи: я также пытался написать другой макрос, который не требует экземпляра структуры, что-то вроде this , но здесь это невозможно - но для меня это не имеет большого значения)

Мой вопрос: это правильно и безопасно? Видите ли вы какую-нибудь потенциальную ловушку или какой-нибудь лучший подход?

Среди прочего: Предполагает ли стандарт C (и де-факто компиляторы), что поля структур находятся в памяти в том же порядке, в каком они определены в исходном коде? Наверное, это глупый вопрос, но я бы хотел убедиться ...

ОБНОВЛЕНИЕ: Некоторые выводы из ответов и моих собственных выводов:

  1. Кажется, с моим подходом проблем нет. В частности, C требует, чтобы поля структуры никогда не меняли порядок.

  2. Можно также (как было предложено ответчиком) считать из последнего постоянного поля и добавить его размер: (char *) & myst.x2 + sizeof ( & myst.x2) - (char *) (& myst) . Это было бы эквивалентно, за исключением того, что в него не включались бы байты заполнения (если они есть) для последнего поля. Очень маленькое преимущество - и очень маленький недостаток, поскольку он менее прост.

  3. Но принятый ответ с смещением кажется предпочтительнее моего предложения. Это ясно-выразительное и чистое время компиляции, для него не требуется экземпляр структуры. Далее он кажется стандартным, доступным в любом компиляторе.

    1. Похоже, с моим подходом проблем нет. В частности, C требует, чтобы поля структуры никогда не меняли порядок.

    2. Можно также (как было предложено ответчиком) считать из последнего постоянного поля и добавить его размер: (char *) & myst.x2 + sizeof ( & myst.x2) - (char *) (& myst) . Это было бы эквивалентно, за исключением того, что в него не входили бы байты заполнения (если они есть) для последнего поля. Очень маленькое преимущество - и очень маленький недостаток, поскольку он менее прост.

    3. Но принятый ответ с смещением кажется предпочтительнее моего предложения. Это ясно-выразительное и чистое время компиляции, для него не требуется экземпляр структуры. Далее он кажется стандартным, доступным в любом компиляторе.

      1. Похоже, с моим подходом проблем нет. В частности, C требует, чтобы поля структуры никогда не меняли порядок.

      2. Можно также (как было предложено ответчиком) считать из последнего постоянного поля и добавить его размер: (char *) & myst.x2 + sizeof ( & myst.x2) - (char *) (& myst) . Это было бы эквивалентно, за исключением того, что в него не включались бы байты заполнения (если они есть) для последнего поля. Очень маленькое преимущество - и очень маленький недостаток, поскольку он менее прост.

      3. Но принятый ответ с смещением кажется предпочтительнее моего предложения. Это ясно-выразительное и чистое время компиляции, для него не требуется экземпляр структуры. Далее он кажется стандартным, доступным в любом компиляторе. C требует, чтобы поля структуры никогда не меняли порядок.

      4. Можно также (как было предложено ответчиком) отсчитывать от последнего постоянного поля и добавлять его размер: (char *) & myst.x2 + sizeof (& myst.x2 ) - (символ *) (& myst) . Это было бы эквивалентно, за исключением того, что в него не включались бы байты заполнения (если они есть) для последнего поля. Очень маленькое преимущество - и очень маленький недостаток, поскольку он менее прост.

      5. Но принятый ответ с смещением кажется предпочтительнее моего предложения. Это ясно-выразительное и чистое время компиляции, для него не требуется экземпляр структуры. Далее он кажется стандартным, доступным в любом компиляторе. C требует, чтобы поля структуры никогда не меняли порядок.

      6. Можно также (как было предложено ответчиком) считать из последнего постоянного поля и добавить его размер: (char *) & myst.x2 + sizeof (& myst.x2 ) - (символ *) (& myst) . Это было бы эквивалентно, за исключением того, что в него не включались бы байты заполнения (если они есть) для последнего поля. Очень маленькое преимущество - и очень маленький недостаток, поскольку он менее прост.

      7. Но принятый ответ с смещением кажется предпочтительнее моего предложения. Это ясно-выразительное и чистое время компиляции, для него не требуется экземпляр структуры. Далее он кажется стандартным, доступным в любом компиляторе. x2 + sizeof (& myst.x2) - (char *) (& myst) . Это было бы эквивалентно, за исключением того, что в него не входили бы байты заполнения (если они есть) для последнего поля. Очень маленькое преимущество - и очень маленький недостаток, поскольку он менее прост.

      8. Но принятый ответ с смещением кажется предпочтительнее моего предложения. Это ясно-выразительное и чистое время компиляции, для него не требуется экземпляр структуры. Далее он кажется стандартным, доступным в любом компиляторе. x2 + sizeof (& myst.x2) - (char *) (& myst) . Это было бы эквивалентно, за исключением того, что в него не входили бы байты заполнения (если они есть) для последнего поля. Очень маленькое преимущество - и очень маленький недостаток, поскольку он менее прост.

      9. Но принятый ответ с смещением кажется предпочтительнее моего предложения. Это ясно-выразительное и чистое время компиляции, для него не требуется экземпляр структуры. Далее он кажется стандартным, доступным в любом компиляторе. Ясно-выразительный и чистый во время компиляции, он не требует экземпляра структуры. Далее он кажется стандартным, доступным в любом компиляторе. Ясно-выразительный и чистый во время компиляции, он не требует экземпляра структуры. Далее он кажется стандартным, доступным в любом компиляторе. Если не требуется конструкция времени компиляции и есть доступный экземпляр структуры (как в моем сценарии), оба решения по сути эквивалентны.

8
задан Community 23 May 2017 в 12:14
поделиться