web-dev-qa-db-fra.com

sizeof membre unique de la structure en C

J'essaie de déclarer une structure qui dépend d'une autre structure ..__ Je veux utiliser sizeof pour être sûr/pédant.

typedef struct _parent
{
  float calc ;
  char text[255] ;
  int used ;
} parent_t ;

Maintenant, je veux déclarer un struct child_t qui a la même taille que parent_t.text.

Comment puis-je faire ceci? (Pseudo-code ci-dessous.)

typedef struct _child
{
  char flag ;
  char text[sizeof(parent_t.text)] ;
  int used ;
} child_t ;

J'ai essayé plusieurs manières avec parent_t et struct _parent, mais mon compilateur n'acceptera pas.

Comme une astuce, cela semble fonctionner:

parent_t* dummy ;
typedef struct _child
{
  char flag ;
  char text[sizeof(dummy->text)] ;
  int used ;
} child_t ;

Est-il possible de déclarer child_t sans utiliser dummy?

88
kevinarpe

Bien que définir la taille du tampon avec un #define soit une façon idiomatique de le faire, une autre solution consisterait à utiliser une macro comme celle-ci:

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

et l'utiliser comme ça:

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

typedef struct
{
    char flag;
    char text[member_size(Parent, text)];
    int used;
} Child;

En fait, je suis un peu surpris que sizeof((type *)0)->member) soit même autorisé comme expression constante. Truc cool.

158
Joey Adams

Je ne suis pas actuellement sur ma machine de développement, mais je pense que vous pouvez effectuer l'une des opérations suivantes:

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

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


Edit : J'aime la macro member_size suggérée par Joey pour l’utilisation de cette technique. Je pense que je l’utiliserais.

25
Brandon Horsley

Utilisez une directive de préprocesseur, c'est-à-dire #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 ;
9
dave mankoff

Vous êtes libre d'utiliser FIELD_SIZEOF(t, f) dans le noyau Linux . Il est simplement défini comme suit:

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

Ce type de macro est mentionné dans d'autres réponses. Mais il est plus portable d’utiliser une macro déjà définie.

6
Dmitry Gladkov

Vous pouvez utiliser une directive de préprocesseur pour la taille, comme suit:

#define TEXT_MAX_SIZE 255

et l'utiliser à la fois parent et enfant.

4
codaddict

Une autre possibilité serait de définir un type. Le fait que vous souhaitiez garantir la même taille pour les deux champs est un indicateur du fait que vous avez la même sémantique pour eux, je pense.

typedef char description[255];

et ensuite avoir un champ

description text;

dans vos deux types.

4
Jens Gustedt

solution c ++:

sizeof (Type :: membre) semble également fonctionner:

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

struct Child
{
    char flag;
    char text[sizeof(Parent::text)];
    int used;
};
4
korish

struct.h les a déjà définis,

#define fldsiz(name, field) \
    (sizeof(((struct name *)0)->field))

afin que vous puissiez,

#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;
}

mais, en regardant dans l'en-tête, il apparaît qu'il s'agit d'un problème BSD et non de la norme ANSI ou POSIX. Je l'ai essayé sur une machine Linux et cela n'a pas fonctionné; utilité limitée.

4
Neil Edelman

@ joey-adams, merci!

#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);
}

Il retourne 20 comme prévu.

Et, @ brandon-horsley, cela fonctionne bien aussi:

#define member_dim(type, member) sizeof(((type){0}).member) / \
                                 sizeof(((type){0}).member[0])
0
Grandma