Hallo Leute,
ich sitze hier schon eine Weile dran:
1
//main.c
2
3
#include<stdio.h>
4
#include<stdlib.h>
5
#include<string.h>
6
7
#include<sub.h>
8
9
voidapp_main(){
10
11
strcpy(string_array,"Hallo");
12
13
printf("%d\n",zahl);
14
printf("%s\n",string_array);
15
16
}
1
//sub.h
2
3
#ifndef SUB_H
4
#define SUB_H
5
6
externintzahl;
7
externcharstring_array[];
8
9
#endif
1
//sub.c
2
3
#include<sub.h>
4
5
voida_task(){
6
7
intzahl=5;
8
charstring_array[100];
9
10
}
Ich bekomme es nicht hin. Wenn ich zahl und string_array aus der
Funktion
eine Ebene nach oben lege (wo sie dann wohl automatisch extern werden)
funktioniert es.
Lass ich die Variablen im Funktionsblock bekomme ich: undefined
reference to ''
W3ll S. schrieb:> Lass ich die Variablen im Funktionsblock bekomme ich: undefined> reference to ''
Logisch, sind ja dann auch lokale Variablen, auf die kannst Du nur
innerhalb der Funktion zugreifen. Entweder lokal oder global, beides
geht nicht.
>..eine Ebene nach oben lege (wo sie dann wohl automatisch extern werden)>funktioniert es.
So werden sie global, nicht extern. Variabeln die du innerhalb einer
Funktion deklarierst sind immer lokal.
W3ll S. schrieb:> wo sie dann wohl automatisch extern werden
Nein.
Das extern kennzeichnet die Deklaration.
Ohne extern ist es eine Definition.
Zombie schrieb:> Entweder lokal oder global,
Es geht noch static.
Ahh, ok danke!
Ich dachte echt, in kann Variablen in einem Headerfile 'extern'
deklarieren, dann in einer Funtion definieren und überall wo ich das
Headerfile einbinde, drauf zugreifen ...
Peter S. schrieb:>>..eine Ebene nach oben lege (wo sie dann wohl automatisch extern werden)>>funktioniert es.>> So werden sie global, nicht extern.
Doch, extern werden sie dadurch auch.
Dirk B. schrieb:> Das extern kennzeichnet die Deklaration.
Ja, im Quellcode macht ein vorgestelltes "extern" eine Deklaration
draus.
> Ohne extern ist es eine Definition.
Dennoch hat die Variable "external linkage". Man kann also von anderen
Übersetzungseinheiten aus darauf zugreifen. Wenn man das vermeiden
wollte, müsste sie static gemacht werden.
W3ll S. schrieb:> dann in einer Funtion definieren und überall wo ich das> Headerfile einbinde, drauf zugreifen
Woher soll der Compiler/Linker denn wissen, welche Funktion gemeint ist?
>Ich dachte echt, in kann Variablen in einem Headerfile 'extern'>deklarieren, dann in einer Funtion definieren und überall wo ich das>Headerfile einbinde, drauf zugreifen ...
Mit 'extern' wird keine Variable deklariert.
=> Damit sagst Du dem Compiler, dass die Variable in einem anderen Modul
(Global) deklariert wird. Der Compiler soll einfach die angegeben
Definition verwenden, der Linker kümmert sich dann um die Refernz, bzw.
meckert wenn er keine Refernz dazu findet.
Der Linker findet die Referenz nicht wenn:
- Die Variable Lokal (=innerhalb einer Funtion) deklariert ist
- Die Variable als 'static' definiert ist (=> Keine Linker Refernz)
Mike schrieb:> Mit 'extern' wird keine Variable deklariert.> => Damit sagst Du dem Compiler, dass die Variable in einem anderen Modul> (Global) deklariert wird.
Ja was denn nun? Deklariert oder nicht?
Mike schrieb:> ..aber statt 'extern' zu nutzen ist es eleganter, globale> Variabeln-Definitionen via Headerfiles zu includieren.
Niemals.
Variablen werden in .c Dateien definiert
Und in Headerdateien - wenn nötig - deklariert.
Die Unterscheidung zwischen Definition und Deklaration macht das extern.
Gibt es Literatur über das Thema, die in kurzen Worten alle Fälle (von
lokalen, globalen und statischen Variablen) abdeckt und in den
Kommentaren etwas beschreibt?
Quasi 4 Dateien (main.c, main.h, thema.c und thema.h)
Noch eine Frage zum Beispiel ganz oben. Muss in main.c nicht a_task()
aufgerufen werden?
Gruß UPW
Mike schrieb:> ..aber statt 'extern' zu nutzen ist es eleganter, globale> Variabeln-Definitionen via Headerfiles zu includieren.
Hallo Mike,
machte mal ein Beispiel bitte?
Jede .c-Datei wird für sich alleine compiliert.
Vorweg läuft noch der Preprozessor. Der ersetzt z.B. die Zeile #include
"meins.h" durch den Inhalt der Datei meins.h
Der eigentliche Compiler sieht von den Preprozessoranweisungen nichts.
Er weiß nichts von anderen Dateien.
Er übersetzt die .c Dateien in Object-Dateien. Diese werden dann (mit
den Bibliotheken) vom Linker zu einer ausführbaren Datei zusammen
gebunden.
Wenn jetzt in einer Headerdatei Variablen definiert werden und dieser
Header in mehreren .c-Dateien inkludiert werden, dann werden diese
Variablen mehrmals angelegt.
Das gefällt dem Linker nicht so gut.
Werden die Variablen aber in der .c definiert und in den Headern
deklariert, gibt es diese Variable nur einmal.
Globale Variablen sollte man so wenig wie möglich nutzen.
Ein globales i (selber gesehen) kann sehr irritierend sein.
W3ll S. schrieb:> Mike schrieb:>> ..aber statt 'extern' zu nutzen ist es eleganter, globale>> Variabeln-Definitionen via Headerfiles zu includieren.>> Hallo Mike,>> machte mal ein Beispiel bitte?
Man könnte das so machen (ungetestet):
Makefile
1
HEADERS=a.hb.h
2
OBJECTS=vars.gen.obla.oblup.o
3
DEPS=$(HEADERS)
4
5
all:myfancyprogram
6
7
# Include everything in one file to make sure all headers are only pulled in once
Einen ganz fieser Fallstrick gibt es bei globalen Variablen, wenn man
sein Projekt nicht nur auf Quellcodeebene schön strukturiert, sondern
die einzelnen Kompilate zunächst zu Bibliotheken linkt und anschließend
diese Bibliotheken, ggf. mit einzelnen Objektdateien, zur eigentlichen
Applikation. Je nach Linkereinstellungen sind globale Variable dann
nicht außerhalb einer Bibliothek sichtbar, und wenn von einem anderen
Programmteil auf solch eine globale Variable zugegriffen werden soll,
wird nämlich daneben gegriffen. Solch ein Problem hatte ich mal vor
ewiger Zeit(tm) bei einer Applikation, die ich von Ultrix auf Windows NT
portieren musste. Wenn ich mich recht einnere, fasste der C-Compiler
unter Ultrix beim Linken gleichnamige globale Variable, die in mehrere
Bibliotheken definiert wurden, zu einer gemeinsamen zusammen. Microsoft
C hingegen legte dann pro Bibliothek eine Instanz an, was meines
Erachtens in den meisten Fällen auch sinnvoll ist, denn gerade bei
fremden Bibliotheken könnte es ja sonst auch zu unbeabsichtigten
Übereinstimmungen kommen.
Wenn man Bibbliotheken zur Verwendung durch Dritte erstellt, sollte man
am Besten auch in einer entsprechenden Linkersteuerdatei explizit die
Symbole benennen, die nach außen sichtbar sein sollen, und alle anderen
Symbole verbergen.