sizeof auf strukturmember

OP #1619264
Lesenswert?

Hi,
Ich habe eingentlich eine total billige Frage, aber ich krieg es grad 
nicht hin:

wie mache ich ein sizeof auf ein Strukturelement, ohne eine Instanz zu 
haben?

Beispiel:

1
typedef struct A
2
{
3
  int b;
4
  int c;
5
}A;
6

7
uint32_t gesamtgroesse = sizeof( A );
8
uint32_t teilgroesseC1  = sizeof( A::c );  // geht nicht
9
uint32_t teilgroesseC2  = sizeof( A.c );   // geht nicht
10

11
A a;
12
uint32_t teilgroesseC3  = sizeof( a.c );   // geht

gibt es keine Möglichkeit diese Größe ohne eine Instanz zu ermitteln?

Gruß,
Vlad
Gast #1619279
Lesenswert?

Vlad Tepesch schrieb:
> gibt es keine Möglichkeit diese Größe ohne eine Instanz zu ermitteln?

Klar.
1
typedef ... Btyp
2
typedef ... Ctyp
3
typedef struct A
4
{
5
  Btyp b;
6
  Ctyp c;
7
}A;
8

9
...  = sizeof( Btyp )
Gast #1619290
Lesenswert?

Vlad Tepesch schrieb:
> das ist auch nur ein Workaround, keine Lösung.
Wenn Du meinst.

Das ist Definitionssache. Wenn meine "Lösung" die einzig mögliche ist 
trifft, "Workaround" wohl nicht zu.

Vlad Tepesch schrieb:
> Erfordert zudem eine Anpassung des Headers in dem die Struktur definiert
> ist.

Das kann ich ja nicht wissen, das Du die Strukturdefinition nicht ändern 
kannst oder willst. Schreib das das nächstemal bitte vorher.
#1619321
Lesenswert?

Vlad Tepesch schrieb:
> eventuell wäre folgendes denkbar:
>
>
1
> uint32_t teilgroesseC  = sizeof( ((A*)0)->c );
2
>
>
> sieht zugegebenermaßen nicht sehr schön aus,

müsste gehen.

> sollte aber keine
> Laufzeitprobleme geben, da sizeof zur Compiletime aufgelöst wird.

Ist auch vom C-Standard gedeckt (oder wars der C++ Standard?) Irgendwo 
bei den Pointern gibt es einen Passus, dass bei einem sizeof das 
'vermeintliche Dereferenzieren' eines 0 Pointers erlaubt ist und dass 
das kein echtes Dereferenzieren darstellt sondern nur von der 
Schreibweise her so aussieht.

(Müsste C++ sein, da in C der sizeof ja mitlerweile nicht mehr 
notwendigerweise eine Compiletime Angelegenheit ist)
Gast #1619324
Lesenswert?

Karl heinz Buchegger schrieb:
> Ist auch vom C-Standard gedeckt (oder wars der C++ Standard?) Irgendwo
> bei den Pointern gibt es einen Passus, dass bei einem sizeof das
> 'vermeintliche Dereferenzieren' eines 0 Pointers erlaubt ist und dass
> das kein echtes Dereferenzieren darstellt sondern nur von der
> Schreibweise her so aussieht.

Aha. Wieder was gelernt.
#1619327
Lesenswert?

Grrrr schrieb:
>
1
uint32_t teilgroesseC  = sizeof( ((A*)0)->c );
2
>
>
> Hauptsache keine Workarounds. Nee, klar. ;-)
> Der nächste Lint-Lauf wird dann auch noch was dazu sagen.

Seine Lösung ist trotzdem besser als deine.

Wenn immer möglich möchte man beim sizeof die Variable angeben und nicht 
den Datentyp.
Sonst hätte er ja auch gleich

uint32_t teilgroesseC2  = sizeof( int );

schreiben können, wohlwissend dass A.c ein int ist. Nur: Ändert A.c 
seinen Datentyp, so passt sich die Pointer Lösung selbst an. In diesem 
Sinne wird daher mehr Arbeit an den Compiler delegiert, was gut ist, 
weil der bei solchen Sachen keinen Fehler macht.
OP #1619360
Lesenswert?

Karl heinz Buchegger schrieb:
> (Müsste C++ sein, da in C der sizeof ja mitlerweile nicht mehr
> notwendigerweise eine Compiletime Angelegenheit ist)

Ist das nicht bei c++ so, dass der sizeof Laufzeitanhängig sein kann?
bei c gibts doch kein RTI
Wäre das bei C der Fall, würde ja aber heißen, das das dereferenzieren 
an der Stelle doch falsch wär.

der Visual c++ compiler schluckt die sache mit dem sizeof(A.c) keine 
Ahnung, ob das eine Eigenheit oder C++ Standard ist. Hab grad kein 
visual C projekt und kein gcc c++ projekt zu Hand.
Gast #1619383
Lesenswert?

Vlad Tepesch schrieb:
> Hab grad kein
> visual C projekt und kein gcc c++ projekt zu Hand.

Ich habs gerade mal durch den avr-gcc gejagt.
Geht ohne Warnings  und i = 2
1
typedef struct A
2
{
3
  int b;
4
  int c;
5
}A;
6

7
short i;
8

9
int main () {
10
  i = sizeof( ((A*)0)->c );
11
}

Nehme also alles zurück und behaupte das Gegenteil.
Gast #1619416
Lesenswert?

Also,
1
uint32_t teilgroesseC  = sizeof( ((A*)0)->c );

ist eine Variablendeklaration mit Initialisierung.

"uint32_t" ist der Typ und "teilgroesseC" der Name der Variablen.

"sizeof( ((A*)0)->c )" ist der Wert der zugewiesen werden soll.

Inhaltlich geht es darum die Grösse eines Mitgliedes der Strukur mit dem 
Typnamen A zu ermitteln, aber ohne das es solch eine Variable 
überhaupt gibt, was heisst sie ist nicht deklariert (oder per malloc 
alloziiert).

"(A*)0"
Daher wird zunächst eine Adresse 0 genommen und mittels "Cast" dem 
Compiler gesagt, er soll annehmen, das eine Variable mit dem Typnamen A 
an dieser Adresse 0 liegt.

Dann wird mittels des "->" (Strukturverweisopator) auf das Mitglied 
namns C verwiesen und mit "sizeof" dessen Grösse ermittelt.
#1619434
Lesenswert?

Vlad Tepesch schrieb:
> Karl heinz Buchegger schrieb:
>> (Müsste C++ sein, da in C der sizeof ja mitlerweile nicht mehr
>> notwendigerweise eine Compiletime Angelegenheit ist)
>
> Ist das nicht bei c++ so, dass der sizeof Laufzeitanhängig sein kann?
> bei c gibts doch kein RTI

Aber bei C gibt es seit C99 dynamische Arrays

int foo( int i )
{
  char array[i];

  j = sizeof( array );
}
Gast #1619652
Lesenswert?

In der AVR stddef.h ister als:

/* Offset of member MEMBER in a struct of type TYPE. */
#define offsetof(TYPE, MEMBER) __builtin_offsetof (TYPE, MEMBER)

watcom macht es so:
#define offsetof(__typ,__id) ((size_t)((char *)&(((__typ*)0)->__id) - 
(char *)0))

MfG
Gast #1619677
Lesenswert?

Vlad Tepesch schrieb:
> Das ist natürlich auch nicht das Wahre, da der Code dann abhängig davon
> ist, dass die Strukturmember immer hintereinander sind und nicht
> verschoben werden.

Welcher Entwickler macht denn sowas? Die Konsequenzen beim umstellen 
sollte man schon im Hinterkopf haben :-)

MfG
Gast #1619678
Lesenswert?

Grrrr schrieb:
> "(A*)0"
> Daher wird zunächst eine Adresse 0 genommen und mittels "Cast" dem
> Compiler gesagt, er soll annehmen, das eine Variable mit dem Typnamen A
> an dieser Adresse 0 liegt.
Danke!
Persönliche Seite #1619807
Lesenswert?

Sauger schrieb:
> Vlad Tepesch schrieb:
>> Das ist natürlich auch nicht das Wahre, da der Code dann abhängig davon
>> ist, dass die Strukturmember immer hintereinander sind und nicht
>> verschoben werden.
>
> Welcher Entwickler macht denn sowas? Die Konsequenzen beim umstellen
> sollte man schon im Hinterkopf haben :-)

Ich glaube du hast das Missverstanden. Was ist, wenn man die 
Konsequenzen grad nicht im Kopf hat? Und eben was umstellt und einen Tag 
nach dem Fehler sucht?
#1619821
Lesenswert?

Sauger schrieb:
> Vlad Tepesch schrieb:
>> Das ist natürlich auch nicht das Wahre, da der Code dann abhängig davon
>> ist, dass die Strukturmember immer hintereinander sind und nicht
>> verschoben werden.
>
> Welcher Entwickler macht denn sowas? Die Konsequenzen beim umstellen
> sollte man schon im Hinterkopf haben :-)

Idealerweise kann man in einer Struktur umstellen wie man lustig ist, 
solange diese Struktur nicht als Bindeglied zu einem anderen Programm 
fungiert, also eine I/O Struktur ist.
Bei letzterem heißt es sowieso besondere Vorsicht walten zu lassen und 
da ist dann auch ein Kommentar angebracht, dass die Struktur genauso 
aussieht wie sie aussieht, weil sich fremde Programme oder Fileaufbauten 
darauf verlassen.

In allen anderen Fällen sollte man sich der Konsequenzen eines 
Strukturumbaus bewusst sein, wie du richtig sagst aber den falschen 
Schluss ziehst, und den Code so aufbauen, dass sich eine Änderung nicht 
auswirkt.

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren