in zwei c files volatile variablen mit selbem namen

Gast #7206463
Lesenswert?

Hallo,

wenn ich in zwei verschiedenen c-files eine statisch volatile variable 
mit dem selben namen habe
file_1.c
1
static volatile uint8_t break = 0;
file_2.c
1
static volatile uint8_t break = 0;

kommen die sich in die quere? Nein, da diese statisch sind und nur für 
die Datei gelten? volatile sagt ja, dass es von außen zugegriffen werden 
kann.
Wie wäre es, wenn ich das static weglassen würde
#7206478
Lesenswert?

marcel schrieb:
> volatile sagt ja, dass es von außen zugegriffen werden
> kann.

Sicher? Ich kenne volatile nur so, das dies für die Variable bedeutet, 
dass diese zur Weiterverarbeitung immer aktualisiert werden muss und 
nicht der zuletzt bekannte Wert genutzt werden darf. Sonst verpasst man 
z.B. die Änderung, welche in einem Interrupt durchgeführt wurde.

Hast du die Variablen innerhalb einer Funktion oder global für die ganze 
c-File definiert? Das macht nämlich einen Unterschied bei static!
Gast #7206479
Lesenswert?

Hallo,

static macht ja nur innerhalb einer Prozedur / Funktion sinn!
(nicht als globale Variable, da sie da automatisch "static" ist)
Innerhalb definiert sind die Variablen aber lokal und lokale Variable 
machen globale Variable mit gleichem Namen unsichtbar.
#7206484
Lesenswert?

Elektrolurch schrieb:
> static macht ja nur innerhalb einer Prozedur / Funktion sinn!
> (nicht als globale Variable, da sie da automatisch "static" ist)

Es gibt zwei Aspekte:
- wo der Name bekannt ist (scope),
- wo die Variable liegt (storage class).

Ein "static" ausserhalb einer Funktion beeinflusst nur wo man sie kennt, 
innerhalb einer Funktion nur wo sie liegt. So hat man anno dunnemal ein 
Keyword eingespart und seither Leute verwirrt.
#7206487
Lesenswert?

marcel schrieb:
> Wie wäre es, wenn ich das static weglassen würde

Wenn Du das static weg lässt, dann macht der Linker daraus eine 
Variable. Könnte eine Warning generieren (doppelter Identifier).

Mit dem Static ist es eine Variable pro Quellen Datei, der Linker 
allokiert also unterschiedliche Adressen. Kann man ausprobieren indem 
man sich z.B. via Debugger die Adresse anzeigen lässt.

Mit "volatile" kennzeichnet man den Zugriff "von außern" aber mit 
"static" ist der Name nur in der konkreten Quelldatei bekannt. Und ja, 
auch die Kombination ist sinnvoll, z.B. wenn Interrupts oder DMA im 
Spiel sind.

Elektrolurch schrieb:
> static macht ja nur innerhalb einer Prozedur / Funktion sinn!
> (nicht als globale Variable, da sie da automatisch "static" ist)

Wenn man keine Ahnung hat... </Nuhrzitat>
Gast #7206499
Lesenswert?

Christian W. schrieb:
> Sicher? Ich kenne volatile nur so, das dies für die Variable bedeutet,
> dass diese zur Weiterverarbeitung immer aktualisiert werden muss und
> nicht der zuletzt bekannte Wert genutzt werden darf. Sonst verpasst man
> z.B. die Änderung, welche in einem Interrupt durchgeführt wurde.

Ja, da habe ich mich schlecht (sehr schlecht) ausgedrückt.
Das meinte ich aber. Also von Aussen in einem Interrupt.

Christian W. schrieb:
> Hast du die Variablen innerhalb einer Funktion oder global für die ganze
> c-File definiert? Das macht nämlich einen Unterschied bei static!

die ist für die c-file.

Hintergrund ist der, dann kann ich in der c-file irgendwo break 
reinschreiben und habe dort zum debuggen definitiv einen Breakpoint 
welcher nicht wegoptimiert wird.
Gast #7206504
Lesenswert?

Olaf schrieb:
> Anmerkung: Glaubt du es ist ein Zeichen von Klugheit eine Variable
>            zu verwenden die "break" heisst?

ja, wenn man für 5 zeichen schon zu faul ist :/
break würde/wird wahrscheinlich nicht gehen.

nenne diese auch immer breakpoint.

Grund ist, dass ich diese als breakpoint verwende
z.B.
1
... ...
2
if(a != 2)
3
{
4
  breakpoint++;
5
}
6
... ...
dort kann ich dann sicher sein, dass dieser nicht wegoptimiert wird, und 
so beim debuggen ein stop setzen kann wenn eine bestimmte bedingung 
eingetreten ist.
Gast #7206520
Lesenswert?

marcel schrieb:
> static volatile uint8_t break = 0;

Wozu?
Das sind im Grunde zwei Dinge:
1. Vereinbaren von Speicherplatz für die Variable
2. Befüllen der Variablen mit einem Wert.

Also im Grunde so:

char break;

und dann in der zugehörigen Funktion irgendwo
 break = 0;

Und das ganze Gehampel nur deshalb, weil man gelegentlich in Funktionen 
auch Variablen braucht, die persistent sind und deshalb nicht auf dem 
Stack sondern ohne Stack direkt irgendwo im RAM angeordnet sind. Aber 
zugleich will man aus Ideologie-Gründen normale Variablen direkt im RAM 
vermeiden, genauso wie man Marke und goto vermeiden will und deshalb 
Anweisungen verwendet, die eigentlich für was anderes gedacht sind.

Und ja, der Linker meckert bei sowas gewiß, denn jede 'static' Variable 
kommt direkt in den RAM und nicht per Stackpointer irgendwo hin je nach 
Programmablauf und so hat der Linker es mit zwei namensgleichen 
Variablen zu tun, wenn nicht zuvor der Compiler oder Assembler da etwas 
dran herum macht. Das ist eben so, weil C kein Modulsystem kennt und die 
gegenseitige Bekanntgabe von Namen entweder mit vorgestelltem 'extern' 
oder durch Einbindung von Headerdateien erfolgt. Also völlig ungeregelt. 
Wenn man das als Programmierer beherzigt und geeignete Namen verwendet, 
die von sich aus nicht mit anderen Namen kollidieren, dann kann man sich 
auch solche Krücken wie 'static' ersparen.

Und nochwas: Namen, die Schlüsselwörtern entsprechen, sollte man lieber 
vermeiden. Nenne deine Variable lieber ottokar oder mybreak. Oder stelle 
deine Programmierweise um, so daß du so etwas garnicht benötigst.

W.S.
Gast #7206575
Lesenswert?

W.S. schrieb:
> Anweisungen verwendet, die eigentlich für was anderes gedacht sind.

Übersetze static einfach mit "stationär". Dann erschließt es sich: Die 
Variable ist hier stationär.

> gegenseitige Bekanntgabe von Namen entweder mit vorgestelltem 'extern'
> oder durch Einbindung von Headerdateien erfolgt. Also völlig ungeregelt.

Nicht ODER.

Header-Dateien bieten die Möglichkeit, Codezeilen in mehrere Files 
einzubinden.
extern macht z.B. Variablen bekannt. Geregelt ist das sehr genau. Du 
bist nur nicht zu obskuren Anordnungen gezwungen.


> Wenn man das als Programmierer beherzigt und geeignete Namen verwendet,
> die von sich aus nicht mit anderen Namen kollidieren, dann kann man sich
> auch solche Krücken wie 'static' ersparen.
Das fördert aber nicht immer die Lesbarkeit. While ist nicht deshalb 
nutzlos, weil ich es durch for ersetzen könnte.
#7206584
Lesenswert?

Christian W. schrieb:
> Sicher? Ich kenne volatile nur so, das dies für die Variable bedeutet,
> dass diese zur Weiterverarbeitung immer aktualisiert werden muss und
> nicht der zuletzt bekannte Wert genutzt werden darf. Sonst verpasst man
> z.B. die Änderung, welche in einem Interrupt durchgeführt wurde.

Nicht ganz. volatile sagt dem Compiler nur, dass er sie nicht optimieren 
darf. Hintergrund dazu ist, dass sich die Variable ändern kann ohne dass 
dies der Compiler erkennt. Dein Beispiel mit dem Interrupt ist so eine 
Sache: Wird eine Variable nur im Interrupt geändert und in der Main-Loop 
wird lediglich darauf nur zugegriffen kann sie dem Compiler als 
Konstante erscheinen und er optimiert ggf. Vergleiche und ähnliches mit 
ihr einfach weg.
#7206593
Lesenswert?

Theoretisch geht es 2 gleiche Variablen dateistatisch
in verschiedenen c- Dateien zu haben.
Praktich ist es aber kacke 2 gleiche Variablen auf den selben
Port verweisen zu lassen, wenn ichs hier richtig verstanden hab.

Denn...
Woher sollen die Routinen in den getrennten C- Dateien wissen,
wer gerad auf den Port zugreift?
Da dürfte es dann Wettrenn-Erscheinungen kommen, die dann Dein Proggy 
blockieren---
Fazit:
Bei mir dürfte nur die Routinen einer C-Datei auf den Port zugreifen.


mfg
#7206620
Lesenswert?

static volatile kann man schreiben, wenn der Interrupthandler und die 
Mainfunktion im selben C-File sind.

marcel schrieb:
> Wie wäre es, wenn ich das static weglassen würde

Dann werden sie vom GCC auf die selbe Adresse gelinkt.
Bei anderen Compilern muß das aber nicht sein, daher gibt es eine 
Warnung.
Die saubere Lösung ist daher, sie nur in einem C-File zu definieren und 
in alle anderen eine Deklaration zu includieren.
#7206645
Lesenswert?

Wilhelm M. schrieb:
> Peter D. schrieb:
>> marcel schrieb:
>>> Wie wäre es, wenn ich das static weglassen würde
>>
>> Dann werden sie vom GCC auf die selbe Adresse gelinkt.
>
> Nein. Es gibt einen Fehler wegen Verletzung der ODR.

Aber erst seit gcc  10. Frühere Versionen hatten -fcommon als default, 
das das von Peter genannte Verhalten zeigt.

Und wie immer: C++ ist nicht C.

Oliver
Gast #7206652
Lesenswert?

Jim M. schrieb:
> marcel schrieb:
>> Wie wäre es, wenn ich das static weglassen würde
>
> Wenn Du das static weg lässt, dann macht der Linker daraus eine
> Variable. Könnte eine Warning generieren (doppelter Identifier).

Wilhelm M. schrieb:
>> Dann werden sie vom GCC auf die selbe Adresse gelinkt.
>
> Nein. Es gibt einen Fehler wegen Verletzung der ODR.

Denn ist das ja eindeutig geklärt...
#7206683
Lesenswert?

Oliver S. schrieb:
> Wilhelm M. schrieb:
>> Peter D. schrieb:
>>> marcel schrieb:
>>>> Wie wäre es, wenn ich das static weglassen würde
>>>
>>> Dann werden sie vom GCC auf die selbe Adresse gelinkt.
>>
>> Nein. Es gibt einen Fehler wegen Verletzung der ODR.
>
> Aber erst seit gcc  10. Frühere Versionen hatten -fcommon als default,
> das das von Peter genannte Verhalten zeigt.

C kennt die sogenannten "tentative definitions" (dürfen keine 
initializer haben). Nur diese können mit -fcommon zusammengefasst 
werden. Dies trifft aber für das obige Beispiel nicht zu. Dort sind es 
wegen des Initializers "echte" Definitionen mit external linkage, was 
zur Verletzung der ODR führt.
Gast #7206689
Lesenswert?

A. S. schrieb:
> Übersetze static einfach mit "stationär". Dann erschließt es sich: Die
> Variable ist hier stationär.

Man hätte auch 'typedef' anders benennen können, aber das Grundproblem 
ist, daß hier versucht wird, irgendwelche Variablen, die eigentlich in 
eine Deklaration außerhalb von Funktionen gehören, so zu deklarieren, 
daß keiner außerhalb eben der betreffenden Funktion drauf zugreifen 
kann.

Wozu?

Eigentlich nur, um Leute zu disziplinieren, die sich partout daneben 
benehmen wollen und ihre Finger nicht von Innereien anderer Funktionen 
weglassen können.
OK, es hat auch mit dem fehlenden Modulsystem bei C zu tun. Wenn man 
nicht die Möglichkeit hat, die Namen von Variablen und Funktionen 
dediziert zu exportieren oder ebenso dediziert es eben nicht zu tun, 
dann landet man schlußendlich bei solchen Verrenkungen. Hier haben wir 
ja einen, der zwei namensgleiche Variablen in zwei verschiedenen Modulen 
hinschreiben will und dann noch fragt, ob das eventuell ein Problem 
geben könnte.

Peter D. schrieb:
> Dann werden sie vom GCC auf die selbe Adresse gelinkt.
> Bei anderen Compilern muß das aber nicht sein,...

Du bist mal wieder sehr auf den GCC orientiert. Nun, es gibt nicht nur 
andere C-Compiler, sondern sogar noch andere Programmiersprachen, wo so 
etwas ganz anders geregelt ist.

A. S. schrieb:
> extern macht z.B. Variablen bekannt. Geregelt ist das sehr genau. Du
> bist nur nicht zu obskuren Anordnungen gezwungen.

Also, man kann zwecks Bekanntmachung von Namen:
1. eine Datei - gemeinhin Headerdatei genannt - inkludieren, wo dann die 
Bezeichnungen drinstehen. Jede andere Text-Datei würde das auch tun, 
vorausgesetzt, dort steht das Richtige drin.
2. einfach ein 'extern' vor eine Deklaration schreiben. Ohne irgend eine 
inkludierte Datei. Man sollte so etwas besser nicht tun, aber es geht 
und widerspricht nicht der Sprachdefinition.

Und was obskure Anweisungen betrifft, erachte ich ein
for(;;) {...}
oder ein
while(true) {...}
als obskur. Denn sowohl for als auch while wurden eigentlich für 
abgezählte oder bedingte Schleifen erfunden - aber nicht für 
bedingungslose.

W.S.
Gast #7206707
Lesenswert?

> 1. eine Datei - gemeinhin Headerdatei genannt - inkludieren, wo dann die

Ich hab in meinen headerdateien immer sowas

#ifdef MAIN
uint8_t dumdidum;
#else
extern uint8_t dumdidum;
#endif

und in main.c:

#define MAIN

#include ...

Dann gibt es jede Variable nur einmal. Und das natuerlich nur in 
begruendeten Ausnahmefaellen und niemals heissen die wie 
Schluesselworte. .-)

Olaf
Gast #7206751
Lesenswert?

Olaf schrieb:
> Ich hab in meinen headerdateien immer sowas

Warum?
Wenn Du doch beides schreiben musst und noch was zusätzlich, ist es doch 
mehr Arbeit und weniger lesbar.

Wenn, dann extern wegzaubern. Ist auch blöd, aber nur eine Stelle.

Und geprüft wird bei Dir nicht (ganz böse)
Moderator Persönliche Seite #7206755
Lesenswert?

Olaf schrieb:
> #ifdef MAIN
> uint8_t dumdidum;
> #else
> extern uint8_t dumdidum;
> #endif

Das geht auch so, dass man die Variablen nur einmal hinschreiben muss:
1
#ifdef MAIN
2
#define EXT
3
#define E_INIT(x) = (x)
4
#else
5
#define EXT extern
6
#define E_INIT(x)
7
#endif
8

9
EXT int foo E_INIT(42);
10
EXT char * bar E_INIT("Alle meine Entchen");
11
...

Das ist aber Geschmackssache. Früher habe ich solche Konstrukte genutzt, 
später eher darauf verzichtet.
#7206867
Lesenswert?

Olaf schrieb:
>> 1. eine Datei - gemeinhin Headerdatei genannt - inkludieren, wo dann die
>
> Ich hab in meinen headerdateien immer sowas
>
> #ifdef MAIN
> uint8_t dumdidum;
> #else
> extern uint8_t dumdidum;
> #endif
>
> und in main.c:
>
> #define MAIN
>
> #include ...

Das sind so typische Sachen, die Hobby- oder Heldenprogrammierer machen: 
sie denken, es sei cool, wenig hinzuschreiben bzw. das Leben für den 
Ersteller (sich selbst) einfach zu machen. Im echten Leben schreibt man 
Code aber für andere Leute, die nicht überrascht werden wollen, wenn sie 
ein Artefakt anschauen. Und hier wird man überrascht, weil in der 
Headerdatei nun zu den Deklarationen auch noch die Definitionen stehen, 
die vermutlich in einer ganz anderen Implementierungsdatei stehen 
sollten.
Moderator Persönliche Seite #7206882
Lesenswert?

Wilhelm M. schrieb:
> Und hier wird man überrascht, weil in der Headerdatei nun zu den
> Deklarationen auch noch die Definitionen stehen, die vermutlich in einer
> ganz anderen Implementierungsdatei stehen sollten.

Eben, genau deshalb mache ich das wie oben beschrieben schon lange nicht 
mehr, diese Vermengung von Definition und Deklaration ist wirklich nicht 
sauber. Das verhindert auch die Wiederverwendbarkeit von Source-Modulen 
in anderen Projekten, macht es zumindest schwerer, den Source weiter zu 
verwenden.

Meiner Meinung gehört in eine Header-Datei lediglich das Interface rein. 
Das kann unter bestimmten Umständen auch mal eine globale Variable als 
externe Deklaration sein - aber mehr nicht.

Ich schrieb dazu auch:

Frank M. schrieb:
> Das ist aber Geschmackssache. Früher habe ich solche Konstrukte genutzt,
> später eher darauf verzichtet.

Ich hatte hier eher auf die technische Möglichkeit mittels Makros 
hingewiesen, nicht, dass ich diesen "Makro-Trick" gut finde. Hier 
scheinen aber einige nicht genau lesen zu können.
Gast #7207191
Lesenswert?

Frank M. schrieb:
> Das kann unter bestimmten Umständen auch mal eine globale Variable als
> externe Deklaration sein - aber mehr nicht.

Wenn man die Variablen in einem Modul geordnet per .h den anderen 
Programmteilen kundgeben will, dann schreibt man sie mit vorangestelltem 
'extern' in die .h und ohne dieses in seine .c und man kann das ebenso 
mit Funktionen tun. So etwas durchzuzuiehen, ist ein Beitrag zur 
Lesbarkeit und auch zur Geradlinigkeit beim Programmieren, obwohl hier 
in diesem Forum gar viele Leute laut aufkreischen, weil es bei 
Funktionen nicht zwingend notwendig ist.
Also etwa so:
in der Emil.h
extern char Ottokar;
extern void Karlheinz (...Karlheizens Parameterliste);

und in der Emil.c
#include "Emil.h"
char Ottokar;
void Karlheinz (...Karlheizens Parameterliste)
{ Inhalt von Karlheinz
}

Das benötigt keinerlei #ifdef Gehampel und ist leserlich. Und wenn 
Emil.h woanders inkludiert wird, ist dort sehr einfach zu ersehen, daß 
Karlheinz keine Forward-Deklaration ist, die in derselben Datei steht, 
sondern etwas Externes ist, das in Emil.c zu finden ist.

W.S.
Gast #7207247
Lesenswert?

>
> Und was obskure Anweisungen betrifft, erachte ich ein
> for(;;) {...}
> oder ein
> while(true) {...}
> als obskur. Denn sowohl for als auch while wurden eigentlich für
> abgezählte oder bedingte Schleifen erfunden - aber nicht für
> bedingungslose.
>
> W.S.

Nur für Leute mit eingeschränktem Gesichtsfeld,
die die Bedingung „immer“ nicht kennen.
Moderator Persönliche Seite #7207397
Lesenswert?

W.S. schrieb:
> Wenn man die Variablen in einem Modul geordnet per .h den anderen
> Programmteilen kundgeben will, dann schreibt man sie mit vorangestelltem
> 'extern' in die .h und ohne dieses in seine .c [...]

Ach.

> und man kann das ebenso mit Funktionen tun.

Man sollte das ebenso mit Funktionen tun. Jeder halbwegs aktuelle 
Compiler aus den letzten 10-20 Jahren schmeisst zumindest eine Warnung 
raus, wenn man eine externe Funktion nicht vorher auch extern deklariert 
hat:
1
$ cat foo.c
2
int main (void)
3
{
4
    foo ();
5
    return 0;
6
}
7

8
$ cc -c foo.c
9
foo.c: In function ‘main’:
10
foo.c:3:5: warning: implicit declaration of function ‘foo’ [-Wimplicit-function-declaration]
11
    3 |     foo ();
Wohlgemerkt: Hier wird nicht gelinkt, sondern nur compiliert.

Mit welchen steinalten Compilern arbeitest Du, dass Du das noch als 
Kann-Option ansiehst? Ich erinnere mich zuletzt an UNIX-Compilern aus 
den 80ern, die so etwas noch ohne Meckern durchließen.

Dass so etwas auch heute noch nur eine Warnung und keinen echten Fehler 
ausgibt, ist der Abwärtskompatibilität zum Ur-C (Kernighan-Ritchie) 
geschuldet. Aber das kann man leicht mit entsprechenden 
Compiler-Switches korrigieren.

P.S.

Ich arbeite zumindest beim gcc mit den Optionen "-Wall -Wextra -Werror", 
also:

- Aktiviere (fast) alle Warnungen
- Aktiviere weitere spezielle Warnungen
- Werte jede Warnung als Fehler und brich dabei die Compilierung ab
Moderator Persönliche Seite #7207409
Lesenswert?

(prx) A. K. schrieb:
> Vor dem Prototyping von ANSI-C war das quasi Sprachstandard, da in einer
> Deklaration einzig der Return-Typ festgelegt wurde, nicht aber die
> Parameter.

Ja, jedoch war schon der Return-Typ wichtig, wenn er nicht gerade "int" 
war. Das förderte natürlich auch die Faulheit: Damals beschränkten sich 
viele Programmierer darauf, nur die Funktionen, die nicht "int" 
zurücklieferten, überhaupt extern zu deklarieren. Denn damals wurde vom 
Compiler einfach alles, was nicht deklariert wurde, als "int" angesehen. 
Macht der gcc natürlich auch heute noch, glücklicherweise aber seit 
einigen Jahrzehnten mit einer entsprechenden Warnung.

> Wer was auf sich hielt, verwendete sowieso "lint" zur Kontrolle.

Ja, das war damals auch mein Werkzeug. Das hat sich dann jedoch mit 
Einführung des Prototyping danach größtenteils erledigt.
Gast #7207442
Lesenswert?

Frank M. schrieb:
> Man sollte das ebenso mit Funktionen tun.

Du hast ihn missverstanden. Die Deklaration einer globalen Funktion ist 
unstrittig.

W.S. geht es meist um das Schlüsselwort extern davor. Das darf 
entfallen und tut es auch meist. Nur wer die Hälfte seines 
Programmierlebens mit PROCEDURE, BEGIN und END verbringt, besteht 
darauf.
#7207462
Lesenswert?

A. S. schrieb:
> W.S. geht es meist um das Schlüsselwort extern davor. Das darf
> entfallen und tut es auch meist. Nur wer die Hälfte seines
> Programmierlebens mit PROCEDURE, BEGIN und END verbringt, besteht
> darauf.

Ich hatte das vor Urzeiten im Compiler mal umgedreht, weil mir das 
extern/static auf den Zeiger ging. Und ein Keyword "global" eingebaut, 
mit dem Funktionen und Variablen external scope bekamen, sondern hatten 
sie file scope. Dieses Verhalten war natürlich per Option wählbar.
Gast #7207516
Lesenswert?

A. S. schrieb:
> W.S. geht es meist um das Schlüsselwort extern davor.

Also....
Diese Empfehlung, extern vor eine Funktionsdeklaration zu schreiben, 
höre ich hier zum ersten mal.
In der Praxis ist mir das auch noch nie aufgefallen, dass das ein 
anderer tut.
Ein Sinn, will mir nicht einleuchten......
Gast #7207551
Lesenswert?

Frank M. schrieb:
>> und man kann das ebenso mit Funktionen tun.
>
> Man sollte das ebenso mit Funktionen tun. Jeder halbwegs aktuelle
> Compiler aus den letzten 10-20 Jahren schmeisst zumindest eine Warnung
> raus, wenn man eine externe Funktion nicht vorher auch extern deklariert
> hat:...

Ähem... nö. Ich stimme dir zu, daß man das 'extern' auch vor die 
Funktionen schreiben sollte, die man in einer .h kundtut. Eben aus 
Gründen der Systematik und damit der Lesbarkeit. Aber mir ist noch nie 
ein C-Compiler begegnet, der das Weglassen von 'extern' moniert hätte. 
Man sollte das eigentlich einbauen.

W.S.
#7207575
Lesenswert?

Wilhelm M. schrieb:
> Das geht bei Variablen nicht, deswegen extern, um die Deklaration von
> der Definition zu unterscheiden.

Doch, auch bei Variablen kann man das unterscheiden: mit und ohne 
expliziter Initialisierung. Früher wurden Variablen ohne sie intern 
routinemässig in Commons umgesetzt (vgl Fortan), weshalb sie beliebig 
oft ohne extern definierbar waren. Kam keine explizit initialisierte 
Definition hinzu, wurden alle solchen Commons gleichen Namens vom Linker 
übereinandergelegt.

Es gab also 3 Stufen:
   extern int unsinn;   // Deklaration
   int unsinn = 1;      // Definition, nur 1x möglich
   int unsinn;          // sowohl Deklaration als auch ggf Definition
#7207584
Lesenswert?

(prx) A. K. schrieb:
> Wilhelm M. schrieb:
>> Das geht bei Variablen nicht, deswegen extern, um die Deklaration von
>> der Definition zu unterscheiden.
>
> Doch, auch bei Variablen kann man das unterscheiden: mit und ohne
> expliziter Initialisierung.

Nicht ganz, hatte ich oben auch schon geschrieben. Was Du meinst, sind 
"tentative definitions", d.h. eine Definition (ohne) extern wird 
(stillschweigend) zu einer Deklaration und kann mit gleichen 
Definitionen in anderen TUs zusammengefasst werden (was normalerweise 
einen Fehler wegen Verletzung der ODR bedeuten würde). Dazu bedarf es 
beim gcc dann noch -fcommon
#7207591
Lesenswert?

(prx) A. K. schrieb:
> Wilhelm M. schrieb:
>> Dazu bedarf es beim gcc dann noch -fcommon
>
> Heute ja, damals war das üblich. Dieses Verhalten früher Compiler
> erklärt, weshalb die Sprache so definiert ist. Der umständliche Zirkus
> von genau 1x ohne extern, sonst mit extern, war damals auch bei vielen
> Variablen unnötig.

Ich denke, der TO ist an einer heutigen Lösung interessiert ;-)
Gast #7207649
Lesenswert?

(prx) A. K. schrieb:
> weshalb sie beliebig
> oft ohne extern definierbar waren. Kam keine explizit initialisierte
> Definition hinzu, wurden alle solchen Commons gleichen Namens vom Linker
> übereinandergelegt.

Kann man sich noch heute mit static auf File-Scope anschauen :-)
1
static int a;
2
...
3
static int a = 7;
4
...
5
static int a;
6

7

8
int dummy(voi)
9
{
10
   return a;
11
}

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