Die gängige Redewendung ist, beides zu verwenden:
typedef struct S {
int x;
} S;
Es handelt sich um unterschiedliche Definitionen. Um die Diskussion klarer zu machen, werde ich den Satz aufteilen:
struct S {
int x;
};
typedef struct S S;
In der ersten Zeile definieren Sie den Bezeichner S
innerhalb des struct-Namensraums (nicht im Sinne von C++). Sie können ihn verwenden und Variablen oder Funktionsargumente des neu definierten Typs definieren, indem Sie den Typ des Arguments als struct S
:
void f( struct S argument ); // struct is required here
Die zweite Zeile fügt einen Typ-Alias hinzu S
in den globalen Namensraum ein und erlaubt Ihnen somit, einfach zu schreiben:
void f( S argument ); // struct keyword no longer needed
Da beide Bezeichner-Namensräume unterschiedlich sind, muss die Definition von S
sowohl in den structs als auch in den global spaces ist kein Fehler, da es sich nicht um eine Neudefinition desselben Bezeichners handelt, sondern um die Erstellung eines anderen Bezeichners an einer anderen Stelle.
Um den Unterschied zu verdeutlichen:
typedef struct S {
int x;
} T;
void S() { } // correct
//void T() {} // error: symbol T already defined as an alias to 'struct S'
Sie können eine Funktion mit dem gleichen Namen wie die Struktur definieren, da die Bezeichner in unterschiedlichen Bereichen gehalten werden, aber Sie können keine Funktion mit dem gleichen Namen wie eine typedef
wenn diese Identifikatoren kollidieren.
In C++ ist es etwas anders, da sich die Regeln für das Auffinden eines Symbols geringfügig geändert haben. In C++ gibt es immer noch zwei verschiedene Bezeichnerbereiche, aber anders als in C müssen Sie das Schlüsselwort struct/class nicht angeben, wenn Sie das Symbol nur innerhalb des Klassenbezeichnerbereichs definieren:
// C++
struct S {
int x;
}; // S defined as a class
void f( S a ); // correct: struct is optional
Was sich ändert, sind die Suchregeln, nicht der Ort, an dem die Bezeichner definiert sind. Der Compiler sucht in der globalen Bezeichnertabelle und nach S
nicht gefunden wurde, sucht es nach S
innerhalb der Klassenbezeichnungen.
Der zuvor vorgestellte Code verhält sich auf dieselbe Weise:
typedef struct S {
int x;
} T;
void S() {} // correct [*]
//void T() {} // error: symbol T already defined as an alias to 'struct S'
Nach der Definition der S
Funktion in der zweiten Zeile, die Struktur S
kann vom Compiler nicht automatisch aufgelöst werden, und um ein Objekt zu erstellen oder ein Argument dieses Typs zu definieren, müssen Sie auf die Einbeziehung der struct
Stichwort:
// previous code here...
int main() {
S();
struct S s;
}
1 Stimmen
Ich habe gerade hier auf SO gelesen, dass die zweite Option einen Compiler-Fehler verursachen würde?! "Übergabe eines Arguments mit inkompatiblem Zeigertyp" stackoverflow.com/questions/12708897/
8 Stimmen
Eine bessere Antwort (meiner Meinung nach) finden Sie unter aquí .