Могу ли я всегда принимать sizeof (GUID) == 16? - PullRequest
5 голосов
/ 05 августа 2011

Определение GUID в заголовках Windows выглядит следующим образом:

typedef struct _GUID {
unsigned long Data1;
unsigned short Data2;
unsigned short Data3;
unsigned char Data4[ 8 ];
} GUID;

Однако упаковка не определена.Поскольку выравнивание элементов структуры зависит от реализации компилятора, можно подумать, что эта структура может иметь длину более 16 байт.

Если я могу предположить, что это всегда 16 байтов - мой код, использующий GUID, более эффективен и прост.Однако это было бы совершенно небезопасно - если компилятор по какой-то причине добавляет некоторые отступы между членами.

Мои вопросы существуют ли потенциальные причины?Или вероятность сценария, что sizeof (GUID)! = 16 на самом деле 0.

Ответы [ 6 ]

3 голосов
/ 05 августа 2011

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

Я хочу сказать, что структуры Windows имеют спецификатор упаковки, но это глобальный параметр, который находится где-то внутри заголовкафайлы.Это #pragma или что-то в этом роде.И это обязательно, потому что иначе программы, скомпилированные разными компиляторами, не могли бы взаимодействовать друг с другом - или даже с самой Windows.

2 голосов
/ 05 августа 2011

Если я чувствую, что мне нужно сделать такое предположение, я добавлю «утверждение времени компиляции» в код. Таким образом, компилятор сообщит мне, если и когда я ошибаюсь.

Если у вас есть или вы хотите использовать Boost, есть макрос BOOST_STATIC_ASSERT, который делает это.

Для моих собственных целей я собрал свою собственную (которая работает на C или C ++ с MSVC, GCC и встроенным компилятором или двумя), в которой используются методы, аналогичные описанным в этой статье:

Реальные трюки для того, чтобы заставить утверждение времени компиляции работать корректно, связаны с тем, что некоторым компиляторам не нравятся объявления, смешанные с кодом (MSVC в режиме C), и что методы часто генерируют предупреждения, которые вы предпочитаете не засорять иначе работающую сборку. Придумывание методов, позволяющих избежать предупреждений, иногда является сложной задачей.

2 голосов
/ 05 августа 2011

Это не ноль, это зависит от вашей системы. Если выравнивание основано на слове (4 байта), вы будете иметь отступ между short s, а размер будет больше 16.

Если вы хотите быть уверены, что это 16 - отключите заполнение вручную, в противном случае используйте sizeof и не принимайте значение.

1 голос
/ 05 августа 2011

Да, на любом компиляторе Windows. В противном случае IsEqualGUID не будет работать: сравниваются только первые 16 байтов. Точно так же любая другая функция WinAPI, которая принимает GUID*, просто проверяет первые 16 байтов.

Обратите внимание, что вы не должны принимать общие правила C или C ++ для windows.h. Например, в Windows байт всегда равен 8 битам, хотя ISO C допускает 9 бит.

1 голос
/ 05 августа 2011

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

Не могли бы вы привести пример упрощенного кода, который вы хотите использовать?Большинство людей просто использовали бы sizeof (GUID), если бы был необходим размер структуры.

С учетом сказанного - я не вижу, чтобы размер GUID когда-либо менялся.

0 голосов
/ 08 января 2012
#include <stdio.h>
#include <rpc.h>
int main () {
GUID myGUID;
printf("size of GUID is %d\n", sizeof(myGUID));
return 0;
}

Есть 16. Это полезно знать, если вам нужно вручную выделить в куче.

...