Какова наилучшая практика для экспорта упакованной структуры, содержащей логические значения?
Я спрашиваю об этом, потому что я пытаюсь найти лучший способ сделать это. Тока я делаю:
#ifndef __cplusplus
#if __STDC_VERSION__ >= 199901L
#include <stdbool.h> //size is 1.
#else
typedef enum {false, true} bool; //sizeof(int)
#endif
#endif
теперь в приведенном выше, размер логического может быть 1 или sizeof(int)
..
Так в структуре, как:
#pragma pack(push, 1)
typedef struct
{
long unsigned int sock;
const char* address;
bool connected;
bool blockmode;
} Sock;
#pragma pack(pop)
выравнивание отличается при использовании C по сравнению с C99 & C ++. Если я экспортирую его как целое число, то языки с логическим размером 1 имеют проблемы с выравниванием и должны дополнить структуру.
Мне было интересно, будет ли лучше использовать определение bool как char в случае с pre-C99, но это не так.
Есть идеи получше?
Это зависит от того, что вы ищете: экономьте место, но выполняйте несколько дополнительных инструкций или тратите несколько байтов, но работайте быстрее.
Если вы хотите быть быстрым, но можете «потратить» несколько байтов пространства (то есть одно значение для каждого логического флага, см. sizeof bool обсуждение), ваш нынешний подход является превосходным. Это потому, что он может загружать и сравнивать логические значения напрямую, без необходимости маскировать их из упакованного поля (см. Далее).
Если вы хотите сэкономить место, вам следует Си битовые поля:
struct Sock {
...
int connected:1; // For 2 flags, you could also use char here.
int blockmode:1;
}
или сверните свои собственные «флаги» и установите биты в целочисленные значения:
#define SOCKFLAGS_NONE 0
#define SOCKFLAGS_CONNECTED (1<<0)
#define SOCKFLAGS_BLOCKMODE (1<<1)
struct Sock {
...
int flags; // For 2 flags, you could also use char here.
}
Оба примера приводят к более или менее одинаковому коду, который маскирует биты и сдвигает значения вокруг (дополнительные инструкции), но плотнее упаковывается, чем простой bool
ценности.
ИМХО, используя #pragma pack
боль больше (в долгосрочной перспективе), чем выигрыш (в краткосрочной перспективе).
Это зависит от компилятора; нестандартный и непереносимый
Я понимаю сценарии встроенных систем или протоколов. Приложив немного дополнительных усилий, код можно написать без прагмы.
Я тоже хочу как можно больше упаковать свою структуру и выложить членов более широко, как вы. Однако я не против потерять 2 байта, если это позволит моему коду соответствовать стандарту и быть переносимым.
Я бы сделал следующие три вещи:
bool
(вы уже сделали) и назначить true/false
struct
(ты уже сделал)Объединяя эти:
typedef struct Sock
{
long unsigned int sock;
const char* address;
bool connected : 1;
bool blockmode : 1;
} Sock;
В случае до C99 это рискованно typedef char bool;
, Это будет молча нарушать код как:
bool x = (foo & 0x100);
который должен установить x
чтобы быть правдой, если этот бит установлен в foo
, Перечисление имеет ту же проблему.
В моем коде я на самом деле typedef unsigned char bool;
но тогда я осторожно пишу !!
везде, где выражение преобразуется в это bool
, Это не идеально.
По моему опыту, использование флагов в интегральном типе приводит к меньшему количеству проблем, чем использование bool
в вашей структуре, или битовые поля, для C90.