sizeof single struct member in C
Я пытаюсь объявить структуру, которая зависит от другой структуры. Я хочу использовать sizeof
быть безопасным / педантичным.
typedef struct _parent
{
float calc ;
char text[255] ;
int used ;
} parent_t ;
Теперь я хочу объявить структуру 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
?
9 ответов
Хотя определение размера буфера с #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 Джои предложил использовать эту технику, я думаю, что я бы использовал это.
Вы можете свободно использовать FIELD_SIZEOF(t, f)
в ядре Linux. Это просто определяется следующим образом:
#define FIELD_SIZEOF(t, f) (sizeof(((t*)0)->f))
Этот тип макроса упоминается в других ответах. Но более переносимым является использование уже определенного макроса.
Используйте директиву препроцессора, например #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 ;
struct.h
они уже определены,
#define fldsiz(name, field) \
(sizeof(((struct name *)0)->field))
чтобы ты мог,
#include <stdlib.h> /* EXIT_SUCCESS */
#include <stdio.h> /* printf */
#include <struct.h> /* 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, и это не сработало; ограниченная полезность.
Вы можете использовать директиву препроцессора для размера как:
#define TEXT_MAX_SIZE 255
и использовать его как в родительском, так и в дочернем.
C++ решение:
sizeof (Type:: member), похоже, тоже работает:
struct Parent
{
float calc;
char text[255];
int used;
};
struct Child
{
char flag;
char text[sizeof(Parent::text)];
int used;
};
Другой возможностью было бы определить тип. Я думаю, тот факт, что вы хотите обеспечить одинаковый размер для двух полей, является показателем того, что у вас одинаковая семантика для них.
typedef char description[255];
а затем есть поле
description text;
в обоих ваших типах.
@ Джои-Адамс, спасибо! Я искал то же самое, но для массива 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])