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
?
Ответы
Ответ 1
Хотя определение размера буфера с помощью #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)
даже разрешен как постоянное выражение. Прохладный материал.
Ответ 2
Сейчас я не на своей машине разработки, но думаю, вы можете сделать одно из следующих:
sizeof(((parent_t *)0)->text)
sizeof(((parent_t){0}).text)
<ч/" > Изменить. Мне нравится макрос member_size. Joey предложил использовать эту технику, я думаю, что буду использовать это.
Ответ 3
Используйте директиву препроцессора, то есть #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 ;
Ответ 4
Вы можете использовать директиву препроцессора для размера как:
#define TEXT_MAX_SIZE 255
и использовать его как в родительском, так и в дочернем.
Ответ 5
Другая возможность - определить тип. Я думаю, что тот факт, что вы хотите обеспечить одинаковый размер для двух полей, является индикатором того, что у вас для них одинаковая семантика.
typedef char description[255];
а затем поле
description text;
в обоих ваших типах.
Ответ 6
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, и это не сработало; ограниченная полезность.
Ответ 7
С++ решение:
sizeof (Тип:: member) также работает:
struct Parent
{
float calc;
char text[255];
int used;
};
struct Child
{
char flag;
char text[sizeof(Parent::text)];
int used;
};
Ответ 8
Вы можете использовать sizeof_field(type, filed)
в Linux.
Он определяется только следующим образом:
#define sizeof_field(type,field) (sizeof(((type *)0)->field))
о котором говорилось выше. Но он более переносимый для использования уже определенного макроса.
Ответ 9
@joey-adams, спасибо!
Я искал то же самое, но для массива 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])