typedef in C

Gast #5657397
Lesenswert?

Hallo zusammen,

ich habe in einer Datei mit dem Namen my_types.h folgendes stehen:
1
typedef struct A_ {
2
  uint8 a;
3
  uint8 b;
4
} A;

Nun gibt es in meinem Projekt mehrere .c Dateien, welche den Typ A 
verwenden. Deshalb habe ich oben in jeder dieser .c Datein oben #include 
"my_types.h" eingetragen.
Beim compilieren bekomme ich jetzt den Fehler, dass der Typ A bereits 
deklariert sei (was ja auch stimmt, weil die my_types.h ja auch für jede 
.c Datei eingebunden wird). Wie kann ich dieses Problem umgehen?
#5657402
Lesenswert?

Georg schrieb:
> Beim compilieren bekomme ich jetzt den Fehler, dass der Typ A bereits
> deklariert sei (was ja auch stimmt, weil die my_types.h ja auch für jede
> .c Datei eingebunden wird).

Das Problem entsteht nicht dadurch, dass es in mehreren .c-Dateien 
eingebunden ist, sondern dass es in einer .c-Datei mehrfach eingebunden 
ist.
Stichwort wäre "include guard".
Moderator Persönliche Seite #5658693
Lesenswert?

Georg schrieb:

>
1
> typedef struct A_ {
2
>   uint8 a;
3
>   uint8 b;
4
> } A;
5
>

Wenn du das Dingens sowieso nie als „struct A_“ benutzen willst, kannst 
du den struct-Namen auch getrost weglassen. Der verunreinigt nur 
unsinnig den Namensraum. Wenn man als generelle Policy alles mit 
typedefs abwickelt, braucht man struct-Namen eigentlich nur, um 
innerhalb der struct-Definition selbst schon darauf zugreifen zu können 
(in Form eines Zeigers).

Außerdem wäre es auch völlig legitim, das Dingens „struct A“ zu nennen. 
In C haben structs einen vom Rest getrennten Namensraum (man definiert 
damit also ein „A“ sowohl im allgemeinen als auch im struct-Raum). In 
C++ wiederum begründet „struct A“ einen Namen „A“, der auch ohne das 
Schlüsselwort „struct“ fürderhin benutzt werden darf, ganz ohne typedef 
- aber ein gleichnamiger typedef ist dennoch gestattet.
Gast #5659091
Lesenswert?

Framulestigo schrieb:
> Die drei gesenkten Daumen sollten Dir reichen. :)
> (Nero halt)

Die Aussage ist aber Quatsch. Wenn ein Strukturname nicht gebraucht wird 
(nie, gar nicht), dann ist der Name über flüssig.

> Sollte man vielleicht in diesem Zusammenhang noch etwas über das
> typische "#ifndef" im Header sagen?

Die Frage war schon lange, ausreichend und richtig beantwortet.
Beitrag #5659093 wurde von einem Moderator gelöscht.
#5659096
Lesenswert?

Ich habe schon öfters gesehen, dass die Compiler sich in den 
Fehlermeldungen dann auf die anonymen structs bezogen haben. Also sowas 
wie
struct unknown4711 has no member x

Deswegen bin ich auch eher dafür, keine anonymen structs zu haben.

Ich kann gerade leider nicht mehr sagen, welche Compiler das waren 
(vielleicht IAR oder TI CCS?). Zuhause habe ich auf die Schnelle mit 
Visual Studio 2017 und Mingw 5.30 getestet und die geben vernünftige 
Fehlermeldungen aus.
Gast #5659176
Lesenswert?

Markus K. schrieb:
> Ich habe schon öfters gesehen, dass die Compiler sich in den
> Fehlermeldungen dann auf die anonymen structs bezogen haben. Also sowas
> wie
> struct unknown4711 has no member x
>
> Deswegen bin ich auch eher dafür, keine anonymen structs zu haben.

Das ist natürlich nicht schön. Der Compiler sollte zumindest in der Lage 
sein, den Namen des neuen Typs in der Fehlermeldung zu nennen. 
Alternativ sowas wie "anonymous struct". Wenn er das nicht macht ist das 
mindestens nen Bugreport wert. Aber ein vernünftiger Compiler gibt ja 
auch die Zeilennummer bei der Fehlermeldung an, so dass es nicht so 
tragisch ist, da man den Fehler ja eh vor Ort beheben muss. Ich sehe da 
keinen Grund gegen anonyme Strukturen.
#5659238
Lesenswert?

mh schrieb:
> Markus K. schrieb:
>> Ich habe schon öfters gesehen, dass die Compiler sich in den
>> Fehlermeldungen dann auf die anonymen structs bezogen haben. Also sowas
>> wie
>> struct unknown4711 has no member x

> Aber ein vernünftiger Compiler gibt ja
> auch die Zeilennummer bei der Fehlermeldung an, so dass es nicht so
> tragisch ist, da man den Fehler ja eh vor Ort beheben muss.

Wenn der Code ein a.x = f.x ist (zwei verschiedene Structs, gleicher 
Membername), dann ist das halt erst der Startpunkt. Dann muss man 
erstmal rausfinden, welches der beiden Structs das war. Wenn das dann 
verschachtelte Structs sind (a.b.c.x = d.e.f.x) und die Unterstützung 
der IDE nicht funktioniert (also kein "Cursor auf die Variable und F10 
drücken", z.B. weil man eine fremde Buildumgebung in ein Visual Studio 
gepackt hat), dann passiert es schnell, dass man sich durch eine 
handvoll header files kämpfen darf bis sieht wo es klemmt. Was man auch 
hätte vermeiden können, wenn wenn man keine anonymen Structs benutzt 
hätte.
Gast #5659316
Lesenswert?

Markus K. schrieb:
> Wenn der Code ein a.x = f.x ist (zwei verschiedene Structs, gleicher
> Membername), dann ist das halt erst der Startpunkt. Dann muss man
> erstmal rausfinden, welches der beiden Structs das war. Wenn das dann
> verschachtelte Structs sind (a.b.c.x = d.e.f.x) und die Unterstützung
> der IDE nicht funktioniert (also kein "Cursor auf die Variable und F10
> drücken", z.B. weil man eine fremde Buildumgebung in ein Visual Studio
> gepackt hat), dann passiert es schnell, dass man sich durch eine
> handvoll header files kämpfen darf bis sieht wo es klemmt. Was man auch
> hätte vermeiden können, wenn wenn man keine anonymen Structs benutzt
> hätte.

Also ein "vierfach wenn" (wenn Membernamen nichtssagend und wenn 
geschachtelte anonyme Strukturen und wenn fehlende Unterstützung durch 
die IDE und wenn mangehafte Fehlermeldung vom Compiler dann verursachen 
anonyme Strukturen etwas mehr Arbeit). Wenn ich mit dir zusammen 
arbeiten würde, würdest du mich damit nicht überzeugen.
#5659405
Lesenswert?

mh schrieb:
> Markus K. schrieb:
>> Wenn der Code ein a.x = f.x ist (zwei verschiedene Structs, gleicher
>> Membername), dann ist das halt erst der Startpunkt. Dann muss man
>> erstmal rausfinden, welches der beiden Structs das war. Wenn das dann
>> verschachtelte Structs sind (a.b.c.x = d.e.f.x) und die Unterstützung
>> der IDE nicht funktioniert (also kein "Cursor auf die Variable und F10
>> drücken", z.B. weil man eine fremde Buildumgebung in ein Visual Studio
>> gepackt hat), dann passiert es schnell, dass man sich durch eine
>> handvoll header files kämpfen darf bis sieht wo es klemmt. Was man auch
>> hätte vermeiden können, wenn wenn man keine anonymen Structs benutzt
>> hätte.
>
> Also ein "vierfach wenn" (wenn Membernamen nichtssagend und wenn
> geschachtelte anonyme Strukturen und wenn fehlende Unterstützung durch
> die IDE und wenn mangehafte Fehlermeldung vom Compiler dann verursachen
> anonyme Strukturen etwas mehr Arbeit). Wenn ich mit dir zusammen
> arbeiten würde, würdest du mich damit nicht überzeugen.

Die Lösung wäre, im Zweifel, um garantiert in jeder Hinsicht portabel zu 
sein, nur den kleinsten gemeinsamen Nenner aus möglichen Compilern, 
möglichen IDEs und möglichen Programmierern zu benutzen.

Zum Glück ist das keine verbindliche Regel.
#5659686
Lesenswert?

mh schrieb:

> Also ein "vierfach wenn" (wenn Membernamen nichtssagend

Das funktioniert leider auch mit guten Namen. Immer wenn man in zwei 
verschiedenen Structs members mit dem gleichen Namen benutzt, z.B. weil 
damit das selbe gemeint ist.

> und wenn geschachtelte anonyme Strukturen

Die Prämisse in der Diskussion war doch, dass man alle Strukturen anonym 
macht. Dann sind auch die geschachtelten Strukturen anonym.

> und wenn fehlende Unterstützung durch die IDE und
> wenn mangehafte Fehlermeldung vom Compiler dann verursachen
> anonyme Strukturen etwas mehr Arbeit).


> Wenn ich mit dir zusammen
> arbeiten würde, würdest du mich damit nicht überzeugen.

Dann wären das a) auch Deine Probleme, also kein absurder Spezialfall, 
sondern Dein Arbeitsalltag und b) war das Argument FÜR anonyme 
Strukturen, dass man so den Namensraum sauber hält - aber wenn man keine 
IDE-Unterstützung hat, dann spielt das m.M. nach eh keine Rolle.
#5659690
Lesenswert?

Rufus Τ. F. schrieb:
>> Die Lösung wäre, im Zweifel, um garantiert in jeder Hinsicht portabel zu
>> sein, nur den kleinsten gemeinsamen Nenner
>
> Das wäre K&R-C, also C noch vor C89.

Mitnichten. Der Schritt von K&R- zu ANSI-C führte zu wesentlich 
verbesserter Portabilität. Die Sprache war davor zu schwach definiert, 
was zu inkompatiblen Compilern führte.

Ich würde auch nicht drauf wetten, dass jeder Compiler überhaupt noch 
K&R akzeptiert.
Gast #5659744
Lesenswert?

Markus K. schrieb:
> Das funktioniert leider auch mit guten Namen. Immer wenn man in zwei
> verschiedenen Structs members mit dem gleichen Namen benutzt, z.B. weil
> damit das selbe gemeint ist.

Aber es ist nur ein Problem, wenn auch die anderen "wenns" erfüllt sind.

Markus K. schrieb:
> Die Prämisse in der Diskussion war doch, dass man alle Strukturen anonym
> macht. Dann sind auch die geschachtelten Strukturen anonym.

Es ging ursprünglich nur um die struct A_.

Markus K. schrieb:
> Dann wären das a) auch Deine Probleme, also kein absurder Spezialfall,
> sondern Dein Arbeitsalltag und b) war das Argument FÜR anonyme
> Strukturen, dass man so den Namensraum sauber hält - aber wenn man keine
> IDE-Unterstützung hat, dann spielt das m.M. nach eh keine Rolle.

Klar wäre es dann auch mein Problem. Aber ich würde das Problem eher 
über eins der anderen "wenns" lösen. Ein besserer Compiler kann ein 
Problem sein, aber eine bessere IDE?

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