sizeof einzelnes Strukturmitglied in C

Lesezeit: 5 Minuten

Benutzeravatar von kevinarpe
Kevinarpe

Ich versuche, eine Struktur zu deklarieren, die von einer anderen Struktur abhängig ist. Ich möchte benutzen sizeof sicher/pedantisch sein.

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

Jetzt möchte ich eine Struktur deklarieren child_t das hat die gleiche größe wie parent_t.text.

Wie kann ich das machen? (Pseudocode unten.)

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

Ich habe versucht, ein paar verschiedene Möglichkeiten mit parent_t und struct _parentaber mein Compiler akzeptiert nicht.

Als Trick scheint das zu funktionieren:

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

Kann man deklarieren child_t ohne Verwendung von dummy?

Benutzeravatar von Joey Adams
Joey Adams

Obwohl die Puffergröße mit a definiert wird #define ist eine idiomatische Möglichkeit, dies zu tun, eine andere wäre, ein Makro wie dieses zu verwenden:

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

Das wundert mich tatsächlich etwas sizeof(((type *)0)->member) ist sogar als konstanter Ausdruck erlaubt. Cooles Zeug.

  • Wow, ich wusste nicht, dass sizeof((type *)0)->member) funktioniert. Bin jetzt nicht auf meinem Entwicklungscomputer, aber funktioniert das für alle Compiler? Danke dafür Joey.

    – Gangadhar

    24. August 2010 um 5:03 Uhr

  • @Gangadhar: Ja, das funktioniert für alle Compiler. Der Operand von sizeof wird nicht ausgewertet, daher gibt es kein Problem mit der Dereferenzierung des Nullzeigers (weil er nicht wirklich dereferenziert wird).

    – James McNellis

    24. August 2010 um 5:50 Uhr

  • wunderbar? sein einfaches C89, siehe Implementierung von “offsetof” in oder dieselbe Implementierung eetimes.com/design/other/4024941/…

    – Benutzer411313

    24. August 2010 um 7:35 Uhr


  • @XavierGeoffrey: Hier leitet sizeof den Typ von ((type *)0)->member ab und gibt die Größe dieses Typs zurück. ((type *)0) ist nur ein Nullzeiger vom Typ struct. ptr->member ist (zur Kompilierzeit) ein Ausdruck, dessen Typ der des Members ist. Der Code innerhalb der Größe von wird nie ausgeführt (wenn dies der Fall wäre, würde das Programm einen Segfault ausführen!). Es wird nur der Werttyp innerhalb von sizeof betrachtet.

    – Joey Adams

    29. September 2014 um 21:13 Uhr

  • Das Wikipedia-Seite für offset_of bemerkt dies als undefiniertes Verhalten gemäß dem C-Standard, daher würde ich nicht darauf wetten, dass es mit allen Compilern funktioniert.

    – Graeme

    3. August 2015 um 15:49 Uhr

Ich bin gerade nicht auf meinem Entwicklungscomputer, aber ich denke, Sie können einen der folgenden Schritte ausführen:

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

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


Bearbeiten: Ich mag das von Joey vorgeschlagene member_size-Makro mit dieser Technik, ich denke, ich würde das verwenden.

  • Die zweite Form ist sehr schön (und konzeptionell sauber, da sie keine Nullzeiger enthält), aber Sie sollten erwähnen, dass dies in Compilern vor C99 nicht möglich ist.

    – R.. GitHub HÖR AUF, EIS ZU HELFEN

    25. August 2010 um 0:09 Uhr

  • Wenn die Struktur sehr groß ist und der Speicher eine Einschränkung darstellt, sollte zuerst eine bevorzugt werden. korrigiert mich jemand, wenn ich falsch liege.

    – PunyCode

    3. August 2021 um 5:20 Uhr

  • @PunyCode – die sizeof Der Operand wird zur Kompilierzeit ausgewertet, also kein Speicherproblem.

    – Johann Gerell

    22. November 2021 um 14:23 Uhr

Benutzeravatar von Dmitry
Dmitri

Die Nutzung steht Ihnen frei FIELD_SIZEOF(t, f) im Linux-Kernel. Es ist einfach wie folgt definiert:

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

Diese Art von Makro wird in anderen Antworten erwähnt. Aber es ist portabler, ein bereits definiertes Makro zu verwenden.

  • FIELD_SIZEOF ist das Makro, das in modernen Linux-Kerneln verwendet wird und in linux/kernel.h zu finden ist

    – Colin Ian König

    18. September 2017 um 9:38 Uhr

  • @ColinIanKing Das ist also ein idiomatischer Weg in C im Allgemeinen, um die Größe des Strukturmitglieds zu erhalten? Ist ein solches Makro noch nicht in einem Standard in modernem C enthalten?

    – St.Antario

    19. Dezember 2018 um 5:32 Uhr

  • Meines Wissens gibt es in Standard-C kein entsprechendes Makro.

    – Colin Ian König

    19. Dezember 2018 um 8:01 Uhr

  • Es war vor kurzem ENTFERNT von linux/kernel.h.

    – Andri Makukha

    18. Februar 2020 um 12:47 Uhr

  • @AndriyMakukha Ich bin auch darauf gestoßen … es heißt jetzt sizeof_field (<linux/stddef.h>) ohne Nettoänderung, nur eine Umbenennung.

    – mirabilos

    13. Juli um 21:23 Uhr

Verwenden Sie eine Präprozessordirektive, dh #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 eine Präprozessordirektive für die Größe wie folgt verwenden:

#define TEXT_MAX_SIZE 255

und verwenden Sie es sowohl bei Eltern als auch bei Kindern.

  • ja, aber es ist nicht immer eine Option: Sagen wir unter Linux /usr/include/bits/dirent.h Die grosse von d_name Feld (Struktur direct / dirent) ist nicht definiert als DIRSIZ nicht mehr, aber fest codiert; Also sizeof() scheint die einzig saubere Möglichkeit zu sein, die Abhängigkeit zu halten

    – ジョージ

    21. Januar 2012 um 17:08 Uhr


Neils Benutzeravatar
Neil

struct.h hat sie bereits definiert,

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

damit du könntest,

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

aber beim Blick in die Kopfzeile scheint es, dass dies eine BSD-Sache und kein ANSI- oder POSIX-Standard ist. Ich habe es auf einem Linux-Rechner versucht und es hat nicht funktioniert; begrenzte Nützlichkeit.

  • ja, aber es ist nicht immer eine Option: Sagen wir unter Linux /usr/include/bits/dirent.h Die grosse von d_name Feld (Struktur direct / dirent) ist nicht definiert als DIRSIZ nicht mehr, aber fest codiert; Also sizeof() scheint die einzig saubere Möglichkeit zu sein, die Abhängigkeit zu halten

    – ジョージ

    21. Januar 2012 um 17:08 Uhr


Benutzeravatar von Jens Gustedt
Jens Gustedt

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 für sie die gleiche Semantik haben, denke ich.

typedef char description[255];

und dann ein Feld haben

description text;

bei beiden Typen.

1423270cookie-checksizeof einzelnes Strukturmitglied in C

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy