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])
Другие вопросы по тегам