Ich versuche, eine Struktur zu deklarieren, die von einer anderen Struktur abhängig ist. Ich möchte sizeof
verwenden, um sicher/pedantisch zu sein.
typedef struct _parent
{
float calc ;
char text[255] ;
int used ;
} parent_t ;
Jetzt möchte ich eine Struktur child_t
deklarieren, die die gleiche Größe wie parent_t.text
hat.
Wie kann ich das machen? (Pseudo-Code unten.)
typedef struct _child
{
char flag ;
char text[sizeof(parent_t.text)] ;
int used ;
} child_t ;
Ich habe verschiedene Möglichkeiten mit parent_t
und struct _parent
ausprobiert, aber mein Compiler akzeptiert dies nicht.
Als Trick scheint das zu funktionieren:
parent_t* dummy ;
typedef struct _child
{
char flag ;
char text[sizeof(dummy->text)] ;
int used ;
} child_t ;
Ist es möglich, child_t
ohne die Verwendung von dummy
zu deklarieren?
Das Definieren der Puffergröße mit einem #define
ist zwar eine idiomatische Methode, aber eine andere wäre die Verwendung eines Makros wie folgt:
#define member_size(type, member) sizeof(((type *)0)->member)
und benutze es so:
typedef struct
{
float calc;
char text[255];
int used;
} Parent;
typedef struct
{
char flag;
char text[member_size(Parent, text)];
int used;
} Child;
Ich bin eigentlich etwas überrascht, dass sizeof((type *)0)->member)
sogar als konstanter Ausdruck erlaubt ist. Cooles Zeug.
Ich bin momentan nicht auf meinem Entwicklungscomputer, aber ich denke, Sie haben folgende Möglichkeiten:
sizeof(((parent_t *)0)->text)
sizeof(((parent_t){0}).text)
Verwenden Sie eine Präprozessor-Direktive, z. B. #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 ;
Sie können FIELD_SIZEOF(t, f)
frei im Linux-Kernel verwenden.
#define FIELD_SIZEOF(t, f) (sizeof(((t*)0)->f))
Diese Art von Makro wird in anderen Antworten erwähnt. Es ist jedoch portabler, ein bereits definiertes Makro zu verwenden.
Sie können eine Präprozessoranweisung für size verwenden als:
#define TEXT_MAX_SIZE 255
und verwenden Sie es bei Eltern und Kind.
Eine andere Möglichkeit wäre, einen Typ zu definieren. Die Tatsache, dass Sie die gleiche Größe für die beiden Felder sicherstellen möchten, ist ein Indikator dafür, dass Sie dieselbe Semantik haben, denke ich.
typedef char description[255];
und dann ein Feld haben
description text;
in beiden Arten.
sizeof (Type :: member) scheint ebenfalls zu funktionieren:
struct Parent
{
float calc;
char text[255];
int used;
};
struct Child
{
char flag;
char text[sizeof(Parent::text)];
int used;
};
struct.h
hat sie bereits definiert,
#define fldsiz(name, field) \
(sizeof(((struct name *)0)->field))
so könntest du,
#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;
}
beim Blick in den Header scheint es sich jedoch um eine BSD-Sache und nicht um den ANSI- oder POSIX-Standard zu handeln. Ich habe es auf einem Linux-Rechner ausprobiert und es hat nicht funktioniert; eingeschränkter Nutzen.
@ joey-adams, danke! Ich suchte dasselbe, aber für ein Array ohne Zeichen und es funktioniert auch so:
#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);
}
Es wird wie erwartet 20 zurückgegeben.
@ Brandon-horsley, das funktioniert auch gut:
#define member_dim(type, member) sizeof(((type){0}).member) / \
sizeof(((type){0}).member[0])