C: sizeof single struct member

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

 typedef struct _parent { float calc ; char text[255] ; int used ; } parent_t ; 

Теперь я хочу объявить struct child_t который имеет тот же размер, что и parent_t.text .

Как я могу это сделать? (Псевдокод ниже).

 typedef struct _child { char flag ; char text[sizeof(parent_t.text)] ; int used ; } child_t ; 

Я пробовал несколько разных способов с parent_t и struct _parent , но мой компилятор не принимает.

Как трюк, похоже, это работает:

 parent_t* dummy ; typedef struct _child { char flag ; char text[sizeof(dummy->text)] ; int used ; } child_t ; 

Можно ли объявить child_t без использования dummy ?

Хотя определение размера буфера с помощью #define – это один идиоматический способ сделать это, другой – использовать макрос следующим образом:

 #define member_size(type, member) sizeof(((type *)0)->member) 

и используйте его так:

 typedef struct { float calc; char text[255]; int used; } Parent; typedef struct { char flag; char text[member_size(Parent, text)]; int used; } Child; 

На самом деле я немного удивлен, что sizeof((type *)0)->member) даже допускается как постоянное выражение. Классная вещь.

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

 sizeof(((parent_t *)0)->text) sizeof(((parent_t){0}).text) 

Редактировать : мне нравится макрос member_size. Джоуи предложил использовать эту технику, я думаю, что буду использовать это.

Используйте директиву препроцессора, то есть #define:

 #define TEXT_LEN 255 typedef struct _parent { float calc ; char text[TEXT_LEN] ; int used ; } parent_t ; typedef struct _child { char flag ; char text[TEXT_LEN] ; int used ; } child_t ; 

Вы можете использовать директиву препроцессора для размера как:

 #define TEXT_MAX_SIZE 255 

и использовать его как в родительском, так и в дочернем.

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

 typedef char description[255]; 

а затем поле

 description text; 

в обоих ваших типах.

struct.h уже определили их,

 #define fldsiz(name, field) \ (sizeof(((struct name *)0)->field)) 

так что вы могли бы,

 #include  /* EXIT_SUCCESS */ #include  /* printf */ #include  /* fldsiz */ struct Penguin { char name[128]; struct Penguin *child[16]; }; static const int name_size = fldsiz(Penguin, name) / sizeof(char); static const int child_size = fldsiz(Penguin, child) / sizeof(struct Penguin *); int main(void) { printf("Penguin.name is %d chars and Penguin.child is %d Penguin *.\n", name_size, child_size); return EXIT_SUCCESS; } 

но, глядя в заголовке, кажется, что это вещь BSD, а не стандарт ANSI или POSIX. Я попробовал это на машине Linux, и это не сработало; ограниченная полезность.

c ++ решение:

sizeof (Тип :: member), похоже, работает также:

 struct Parent { float calc; char text[255]; int used; }; struct Child { char flag; char text[sizeof(Parent::text)]; int used; }; 

Вы можете использовать sizeof_field(type, filed) в Linux. Он определяется только следующим образом:

 #define sizeof_field(type,field) (sizeof(((type *)0)->field)) 

это упомянуто выше. Но более гибко использовать уже определенный макрос.

@ joey-adams, спасибо! Я искал одно и то же, но для массива non char, и он отлично работает даже так:

 #define member_dim(type, member) sizeof(((type*)0)->member) / \ sizeof(((type*)0)->member[0]) struct parent { int array[20]; }; struct child { int array[member_dim(struct parent, array)]; }; int main ( void ) { return member_dim(struct child, array); } 

Он возвращает 20, как ожидалось.

И, @ brandon-horsley, это тоже хорошо работает:

 #define member_dim(type, member) sizeof(((type){0}).member) / \ sizeof(((type){0}).member[0]) 
  • Есть ли способ перебрать структуру с элементами разных типов в C?
  • Что такое «форвардная декларация» и разница между «typedef struct X» и «struct X»?
  • Макет в памяти структуры. структура массивов и массив структур в C / C ++
  • Инициализация структуры языка программирования C / C ++?
  • myView.frame.origin.x = значение; не работает. Но почему?
  • bds 2006 C конфликты с скрытым диспетчером памяти (class new / delete vs. AnsiString)
  • Не уникальные значения enums
  • Почему структуры не поддерживают наследование?
  • c ++ sort с structs
  • Когда вы должны использовать class vs struct в C ++?
  • Разница между 'struct' и 'typedef struct' в C ++?
  • Давайте будем гением компьютера.