Speicherklassen-Modifizierer 'extern'

Moin,

meine Theorie besagt: „Der Speicherklassenmodifizierer extern hat keine Auswirkungen“. Wenn ich eine globale Variable „float x“ innerhalb einer funktion mittels „extern float x“ erneut deklariere, ändert sich ja nix.

Könnt Ihr das so bestätigen?

thx
moe.

Hallo Moe !

Wenn ich eine globale Variable „float
x“ innerhalb einer funktion mittels „extern float x“ erneut
deklariere, ändert sich ja nix.
Könnt Ihr das so bestätigen?

Nein.
Wenn die Variable x in der Datei ‚source1.c‘ global angelegt wird und ich in der Datei ‚source2.c‘ darauf zugreifen will und beim Kompilieren die Datei ‚source1.c‘ nicht zufällig vor der Datei ‚source2.c‘ drankommt kennt der Compiler die Variable x natürlich nicht und liefert einen Compilererror.
Erst durch ‚extern float x‘ teile ich dem Compiler mit, das irgendwo anders im Project eine globale Variable mit dem Namen x und dem Datentyp float angelegt wird und ich hier auf diese zugreifen will.
(Der Linker löst die Adresse dann auf, so dass ich wirklich auf diese Variable zugreife.)

mfg
Christof

Hallo

meine Theorie besagt: „Der Speicherklassenmodifizierer extern
hat keine Auswirkungen“. Wenn ich eine globale Variable „float
x“ innerhalb einer funktion mittels „extern float x“ erneut
deklariere, ändert sich ja nix.

Könnt Ihr das so bestätigen?

Hört sich etwas verkehrt an.

‚extern myName‘ bei traditionellem C
macht nichts anderes, als einen Bezeichner
‚myName‘ in den aktuellen Scope zu importieren.

die tatächliche Definition von ‚myName‘
kann in einer anderen ‚compilation unit‘
(oder in der selben, egal) liegen, der
Linker füllt dann alle ‚extern‘-Importe
mit der Adresse der einen tatsächlichen
Variablen ‚myName‘ - bei der Verlinkung
der Objektmodule.

Grüße

CMБ

Und bei nur einer Datei?
Moin,

stimmt meine Theorie, wenn das Programm nur eine einzige Datei umfasst?

thx
moe.

Hallo

stimmt meine Theorie, wenn das Programm nur
eine einzige Datei umfasst?

Sie ist viellicht nicht gerade falsch,
sondern ‚unzutreffend‘. Sie berührt nicht
den Punkt :wink:

Siehe:

#include 
 
 float myValue = 42; // definition in genau einem der files
 extern float myValue; // extern kann hier weggelassen werden, wenn nur 1 file
 
 int main()
{
 printf( "main 1: %f\n", myValue );

 {
<u>float myValue</u>;
 printf( "\tblock 1: %f\n", myValue );
 myValue = 21;
 printf( "\tblock 1: %f\n", myValue );
 }
 
 printf( "main 2: %f\n", myValue );

 {
<u>extern float myValue</u>;
 printf( "\tblock 2: %f\n", myValue );
 myValue = 21;
 printf( "\tblock 2: %f\n", myValue );
 }

 printf( "main 3: %f\n", myValue );

 return 0;
}

Liefert folgende Ausgabe:

 main 1: <u>42.000000</u>
 block 1: -107374176.000000
 block 1: 21.000000
 main 2: <u>42.000000</u>
 block 2: <u>42.000000</u>
 block 2: 21.000000
 main 3: **21.000000**

Alles klar :wink:

Grüße

CMБ

Hallo

stimmt meine Theorie, wenn das Programm nur
eine einzige Datei umfasst?

Sie ist viellicht nicht gerade falsch,
sondern ‚unzutreffend‘. Sie berührt nicht
den Punkt :wink:

Siehe:

#include

float myValue = 42; // definition in genau einem der files
extern float myValue; // extern kann hier weggelassen werden,
wenn nur 1 file

int main()
{
printf( „main 1: %f\n“, myValue );

{
float myValue;
printf( „\tblock 1: %f\n“, myValue );
myValue = 21;
printf( „\tblock 1: %f\n“, myValue );
}

printf( „main 2: %f\n“, myValue );

{
extern float myValue;
printf( „\tblock 2: %f\n“, myValue );
myValue = 21;
printf( „\tblock 2: %f\n“, myValue );
}

printf( „main 3: %f\n“, myValue );

return 0;
}

Liefert folgende Ausgabe:

main 1: 42.000000
block 1: -107374176.000000
block 1: 21.000000
main 2: 42.000000
block 2: 42.000000
block 2: 21.000000
main 3: 21.000000

Alles klar :wink:

Wenig denn je :wink:

wenn ich „extern float myValue;“ (Zeile 2) und „extern float myValue“ (Block 1) weglasse hat sich nichts verändert… ?! Wozu also? Außer wegen des Stils :wink:

Ich verstehe den Ablauf so:

myValue = 42 ist globale Variable
printf „main 1“ gibt 42 aus
in Block 1 wird die lokale Variable myValue deklariert aber nicht initialisiert
printf „block 1“ ergibt Mumpitz (weil nicht init.)
myValue wird mit 21 initialisiert
printf „block 1“ gibt 21 aus
Der Block ist zu Ende --> myValue (lokal) wird zerstört
printf „main 2“ gibt wieder die gloable myValue = 42 aus, weil es keine lokale gibt.
In Block 2 wird die Deklaration der globalen myValue (mit extern) wiederholt (was nicht nötig wäre)
printf „block 2“ gibt die gloable myValue = 42 aus
die globale myValue wird auf 21 gesetzt
printf „block 2“ gibt die globale myValue = 21 aus
printf „main 3“ gibt die globale myValue = 21 aus, weil keine lokale Variable existiert.

thx
moe.

Hallo

wenn ich „extern float myValue;“ (Zeile 2) und „extern
float myValue“ (Block 1) weglasse hat sich nichts verändert…
?! Wozu also? Außer wegen des Stils :wink:

Nicht unbedingt. ‚extern‘ überschreibt ggf.
auch die bereits eingetretene Gültigkeit
einer (lokalen) Variablen mit dem selben Bezeichner,
siehe:

#include 
 
 float myValue = 42; // definition in genau einem der files

 int main()
{
 float myValue = 21; // lokale Definition ueberschreibt Globale
 printf( "main 1: %f\n", myValue );

 {
 printf( "\tblock 1: %f\n", myValue );
 myValue = 0;
 printf( "\tblock 1: %f\n", myValue );
 }

 printf( "main 2: %f\n", myValue );

 {
<u>extern float myValue</u>; // Globale Variable wird zurueckgeholt
 printf( "\tblock 2: %f\n", myValue );
 myValue = 99;
 printf( "\tblock 2: %f\n", myValue );
 }

{
 printf( "main 3a: %f\n", myValue );
}

{
 <u>extern float myValue</u>;
 printf( "main 3b: %f\n", myValue );
}

 return 0;
}

Was liefern 3a) und 3b) ?

Grüße

CMБ

Hallo moe,

meine Theorie besagt: „Der Speicherklassenmodifizierer extern
hat keine Auswirkungen“. Wenn ich eine globale Variable „float
x“ innerhalb einer funktion mittels „extern float x“ erneut
deklariere, ändert sich ja nix.

Der Compiler erzeugt nicht nur Code, sondern aus Anweisungen zum benötigten Speicher für den Linker.

float x;

teilt dem Linker mit, Speicherplatz für einen Float anzulegen, auf welchen dann mit dem Namen „x“ zugegrifen werden kann.

extern float x;

besagt aber nur, dass irgendwo Speicherplatz für einen Float mit dem Namen „x“ existiert, auf welchen man zugreifen möchte. Der Linker soll dann nach der Stelle suchen wo der Speicherplatz für „x“ angelegt wurde und diese Adresse verwenden.

Wenn du nur eine Datei verwendest, genügt
extern float x;
dem Compiler um ohne zu murren alles zu übersetzen. Erst der Linker macht dann Probleme, weil er nirgends den Speicherplatz für „x“ finden kann.

„extern“ funktioniert auch noch mit FunctionPrototypes, macht aber heute keinen Sinn mehr.

MfG Peter(TOO)
P.S. die nächste Frage kommt dann zu „static“ ??

P.S. die nächste Frage kommt dann zu „static“ ??

Nein, static glaube ich verstanden zu haben, aber keine Sorge, irgendwann steh ich wieder irgendwo auf dem Schlauch :wink:

moe.

Hallo

Nein, static glaube ich verstanden zu haben, aber keine Sorge,
irgendwann steh ich wieder irgendwo auf dem Schlauch :wink:

moe.

Wie ist es denn mit Deiner Hypothese:

meine Theorie besagt:
„Der Speicherklassenmodifizierer extern
hat keine Auswirkungen“

ausgegangen?

Grüße

CMБ

Wie ist es denn mit Deiner Hypothese:

meine Theorie besagt:
„Der Speicherklassenmodifizierer extern
hat keine Auswirkungen“

ausgegangen?

Zunächst Danke für die Unterstützung. An „extern“ muss ich weiter arbeiten. Das letzte Licht ist mir noch nicht aufgegangen, aber ich denke, dass kommt mit der Zeit :wink:

moe.

Danke!!
.