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])