размер одного члена структуры в C - PullRequest
94 голосов
/ 24 августа 2010

Я пытаюсь объявить структуру, которая зависит от другой структуры.Я хочу использовать 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 ]

176 голосов
/ 24 августа 2010

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

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

и использовать его так:1006 *

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

27 голосов
/ 24 августа 2010

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

sizeof(((parent_t *)0)->text)

sizeof(((parent_t){0}).text)

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

9 голосов
/ 24 августа 2010

Используйте директиву препроцессора, например #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 ;
7 голосов
/ 13 марта 2017

Вы можете использовать FIELD_SIZEOF(t, f) в ядре Linux. Это просто определяется следующим образом:

#define FIELD_SIZEOF(t, f) (sizeof(((t*)0)->f))

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

4 голосов
/ 14 июня 2016

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, и это не сработало; ограниченная полезность.

4 голосов
/ 26 февраля 2016

c ++ решение:

sizeof (Type :: member), похоже, тоже работает:

struct Parent
{
    float calc;
    char text[255];
    int used;
};

struct Child
{
    char flag;
    char text[sizeof(Parent::text)];
    int used;
};
4 голосов
/ 24 августа 2010

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

typedef char description[255];

, а затем есть поле

description text;

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

4 голосов
/ 24 августа 2010

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

#define TEXT_MAX_SIZE 255

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

0 голосов
/ 30 сентября 2017

@ Джои-Адамс, спасибо! Я искал то же самое, но для массива 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])
...