Forum: Compiler & IDEs extern void f(){};


von Sina A. (sinapse)


Lesenswert?

Kurze Frage...

ist
1
extern void f(){};

eine Deklaration oder Definition oder beides?

von Dennis S. (eltio)


Lesenswert?

Deklaration, weil hier kein Speicher reserviert wird.

von mir_fällt_keiner_ein (Gast)


Lesenswert?

Erst wenn in den geschweiften Klammern etwas steht, wird die Funktion 
auch definiert. Ansonsten ist es nur eine Deklaration.

von Rolf Magnus (Gast)


Lesenswert?

Sina Anargo schrieb:
> ist
> extern void f(){};
>
> eine Deklaration oder Definition oder beides?

Keins von beiden, da das Semikolon hier nicht erlaubt ist. Ohne 
Semikolon wäre es beides, da es sich um eine Definition handelt und jede 
Definition automatisch auch eine Deklaration ist. Das 'extern' ist 
überflüssig.

mir_fällt_keiner_ein schrieb:
> Erst wenn in den geschweiften Klammern etwas steht, wird die Funktion
> auch definiert. Ansonsten ist es nur eine Deklaration.

Wie kommst du auf den Unsinn? Ob die Funktion leer ist oder nicht, 
spielt keine Rolle.

von Sina A. (sinapse)


Lesenswert?

Rolf Magnus schrieb:
> Keins von beiden, da das Semikolon hier nicht erlaubt ist.

Wieso ist das Semikolon nicht erlaubt?

danke schonmal fuer die antworten

von Ingo (Gast)


Lesenswert?

Sina Anargo schrieb:
> extern void f(){};
Aber warum extern für einen Funktionsprototypen?

von Norbert (Gast)


Lesenswert?

Rolf Magnus schrieb:

>> extern void f(){};

> Keins von beiden, da das Semikolon hier nicht erlaubt ist.
1
//    gcc -Wall -Wextra -o x x.c
2
3
;;;;;
4
extern void f(){;;;;;};;;;;;
5
;;;;
6
7
int main(void) {
8
    ;;;;;
9
    return 0;
10
    ;;;;;
11
};;;;;
12
;;;;;

Rate mal wo hier überall ein ';' erlaubt ist... ;-)

von (prx) A. K. (prx)


Lesenswert?

Sina Anargo schrieb:
> Wieso ist das Semikolon nicht erlaubt?

Weil das in der C Syntax offiziell nicht erlaubt ist. Man hätte es 
erlauben können, hat es aber nicht getan.

Wenn ein Compiler es zulässt, heisst das nicht auch, dass C es zulässt.
1
C99: A.2.4 External definitions
2
3
(6.9) translation-unit:
4
   external-declaration
5
   translation-unit external-declaration
6
7
(6.9) external-declaration:
8
   function-definition
9
   declaration
10
11
(6.9.1) function-definition:
12
   declaration-specifiers declarator declaration-list opt compound-statement
13
14
(6.8.2) compound-statement:
15
   { block-item-list opt }

Da kommt bezogen auf Funktionsdefinitionen mit {} Block kein ; vor.

: Bearbeitet durch User
von (prx) A. K. (prx)


Lesenswert?

Dennis S. schrieb:
> Deklaration, weil hier kein Speicher reserviert wird.

Definition, weil sehr wohl Speicher reserviert wird.

von Rolf Magnus (Gast)


Lesenswert?

Norbert schrieb:
> //    gcc -Wall -Wextra -o x x.c

Und jetzt probiere das selbe mal mit -pedantic.

von (prx) A. K. (prx)


Lesenswert?

Rolf Magnus schrieb:
> Keins von beiden, da das Semikolon hier nicht erlaubt ist.

Schon, das Semikolon gehört aber nicht zur bereits vollständig 
abgeschlossenen Funktionsdefinition. (A.K. mit -pendantic enabled ;-)

von Sina A. (sinapse)


Lesenswert?

Ingo schrieb:
> Aber warum extern für einen Funktionsprototypen?

ich wollte "extern" richtig verstehen. Ursprünglich habe ich das von dem 
folgenden wie ich finde sehr schönen Trick:

include.h
1
#ifndef INLINE
2
  #define INLINE extern inline
3
#endif
4
5
INLINE void f(){};

main.c
1
#define INLINE inline
2
#include "include.h"

alle anderen *.c
1
#include "include.h"

- Damit steht in der main.c inline void f(){} -> wird somit definiert

- während in allen anderen files steht extern inline void f(){} steht -> 
wird somit nur deklariert.

daraus habe ich gefolgert, dass extern eine Deklaration forciert, wenn 
der Funktionsbauch dabei steht. Gleich mal ohne inline ausprobiert, ob 
meine These stimmt:

main.h
1
extern void f(){};  //ist ja nur deklaration nach meiner these

compiliert und siehe: Fehlermeldung "Symbol f multiply defined..."

also doch definition... aber beim inlinen irgendwie anders?? 
Schlussfolgerung ich hab da irgendwas nicht richtig verstanden.  Aber 
wie ist es denn nun genau?

von Norbert (Gast)


Lesenswert?

Rolf Magnus schrieb:
> Norbert schrieb:
>> //    gcc -Wall -Wextra -o x x.c
>
> Und jetzt probiere das selbe mal mit -pedantic.

Ahhh, sehr schön. Wieder etwas gelernt.

von (prx) A. K. (prx)


Lesenswert?

Sina Anargo schrieb:
> Schlussfolgerung ich hab da irgendwas nicht richtig verstanden.  Aber
> wie ist es denn nun genau?

Es sind
   extern int variable;
   extern void f(void);
reine Deklarationen und
   int variable;
   int variable = 1;
   void f(void) { }
reine Definitionen.

Sinnarme Mischformen wie
   extern int variable = 1;
   extern void f(void) { }
sollte man lieber nicht verwenden. Das ist zwar rein syntaktisch kein 
Problem und eindeutig Definition, aber bestenfalls toleriert.

Es gab freilich auch Zeiten, da war in der Praxis
   int variable;
bei vielen Compilern sowohl Deklaration wie Definition, je nachdem was 
anderswo im Programm zum Thema "variable" vorkam.

: Bearbeitet durch User
von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Sina Anargo schrieb:
> ich wollte "extern" richtig verstehen.

"extern" bei Funktionsdeklarationen ist immer überflüssig: man darf
es zwar schreiben, aber es gibt keinen Unterschied zur gleichen
Deklaration ohne "extern".

A. K. schrieb:
> Es gab freilich auch Zeiten, da war in der Praxis
>    int variable;
> bei vielen Compilern sowohl Deklaration wie Definition, je nachdem was
> anderswo im Programm vorkam.

Dieses Verhalten wird vom Standard nach wie vor als eine von beiden
möglichen Verhaltensoptionen akzeptiert.  Es ist eben nur schlechter
Stil, sich darauf zu verlassen, und spätestens, wenn man eine Variable
auch initialisieren will, kommt man um eine saubere "extern"-Deklaration
nicht umnhin.

von Sina A. (sinapse)


Lesenswert?

Also kann man zusammenfassend sagen

extern void f(){};

ist nach C standard verboten, aber je nach dem welchen Compiler man 
nutzt, drücken diese auf unterschiedliche Weise ein Auge zu, so dass man 
Compilerabhängig solche Tricks wie mit dem extern inline oben 
konstruieren kann... funktioniert aber eben nicht mit jedem Compiler 
(zumindest kann man sich nicht sicher sein).

Und da das alles Compilerabhängig ist, braucht man nicht weiter über 
eine tiefere Logik von extern nachdenken??

von (prx) A. K. (prx)


Lesenswert?

Sina Anargo schrieb:
> - während in allen anderen files steht extern inline void f(){} steht ->
> wird somit nur deklariert.

Mit "inline" ist das wieder eine andere Baustelle, denn während
  extern void f(void) {}
eine vollständige Definition ist, ist das bei
  extern inline void f(void) {}
nicht der Fall: "An inline definition does not provide an external 
definition for the function, and does not forbid an external definition 
in another translation unit."

An dieser Stelle wird das Eis ziemlich dünn, auf dem man sich bewegt.

: Bearbeitet durch User
von Karl H. (kbuchegg)


Lesenswert?

Sina Anargo schrieb:

> also doch definition... aber beim inlinen irgendwie anders??
> Schlussfolgerung ich hab da irgendwas nicht richtig verstanden.  Aber
> wie ist es denn nun genau?

Als Daumenregel könnte man zusammenfassen: Wenn 'extern' (welches 
eigentlich eine Deklaration anzeigt) mit der Tatsache kollidiert, dass 
etwas eine Definition sein könnte, dann "verliert" das extern und es ist 
eine Definition.

Dieser Grundsatz klärt Dinge wie
1
extern int Werte[] = { 1, 2, 3, 4 };
Das hier kann keine Deklaration sein, selbst wenn da ein extern 
angeführt ist. Denn hier existiert eine Initialisierung und 
Initialisierungen gibt es nur bei Definitionen. Daher verliert die 
Deklaration und das ganze ist eine Definition.

Selbiges in deinem Fall mit der Funktion.

: Bearbeitet durch User
von (prx) A. K. (prx)


Lesenswert?

Karl Heinz schrieb:
> Als Daumenregel könnte man zusammenfassen: Wenn 'extern' (welches
> eigentlich eine Deklaration anzeigt) mit der Tatsache kollidiert, dass
> etwas eine Definition sein könnte, dann "verliert" das extern und es ist
> eine Definition.

Ausser bei "inline", denn
  extern void f(void) {}
erzeugt eine global verfügbare Funktion, während
  extern inline void f(void) {}
das nicht tut. ;-)

von (prx) A. K. (prx)


Lesenswert?

Karl Heinz schrieb:
> Dieser Grundsatz klärt Dinge wie

Wobei das von GCC auch ohne jede Pendantik mit einer Warnung quittiert 
wird. Bei Funktionen freilich stört ihn das Äquivalent nicht.

: Bearbeitet durch User
von (prx) A. K. (prx)


Lesenswert?

Sina Anargo schrieb:
> Also kann man zusammenfassend sagen

... dass man so etwas wie ...

> extern void f(){};

... lieber nicht verwenden sollte. Mit oder ohne "inline".

von Sina A. (sinapse)


Lesenswert?

thx an alle

von Rolf Magnus (Gast)


Lesenswert?

A. K. schrieb:
> Es sind
[...]
>    int variable;
>    int variable = 1;
>    void f(void) { }
> reine Definitionen.

Seit wann ist eine Definition keine Deklaration mehr?

> Es gab freilich auch Zeiten, da war in der Praxis
>    int variable;
> bei vielen Compilern sowohl Deklaration wie Definition, je nachdem was
> anderswo im Programm zum Thema "variable" vorkam.

Warum sollte es denn keine Deklaration mehr sein? Das hieße ja, daß 
folgender Code fehlerhaft wäre:
1
int variable;
2
3
int main()
4
{
5
    variable = 3;
6
}

von (prx) A. K. (prx)


Lesenswert?

Rolf Magnus schrieb:
> Seit wann ist eine Definition keine Deklaration mehr?

In meiner Betrachtungsweise enthält eine Definition auch die Bedeutung 
einer Deklaration. Insofern sehe ich keine Widerspruch. Aber ich sehe, 
dass du genau wie ich auch ein -pendantic Flag hast. ;-)

> Warum sollte es denn keine Deklaration mehr sein?

Das bezog sich auf den Fall:
  file1: int variable;
  file2: int variable = 1;
Das in file1 ist nur dann eine Definition, wenn file2 fehlt. Mit file2 
ist es eine Deklaration.

: Bearbeitet durch User
von Rolf Magnus (Gast)


Lesenswert?

A. K. schrieb:
> In meiner Betrachtungsweise enthält eine Definition auch die Bedeutung
> einer Deklaration. Insofern sehe ich keine Widerspruch.

Nun gut, für mich bedeutet es, dass eine Definition auch eine 
Deklaration ist. Aber ich hab verstanden, wie du es meinst.

> Das bezog sich auf den Fall:
>   file1: int variable;
>   file2: int variable = 1;
> Das in file1 ist nur dann eine Definition, wenn file2 fehlt. Mit file2
> ist es eine Deklaration.

Aber das war in genormtem C noch nie so, oder?

von Andreas S. (Firma: Schweigstill IT) (schweigstill) Benutzerseite


Lesenswert?

Jörg Wunsch schrieb:
> "extern" bei Funktionsdeklarationen ist immer überflüssig: man darf
> es zwar schreiben, aber es gibt keinen Unterschied zur gleichen
> Deklaration ohne "extern".

Das ist falsch, denn für
1
extern void a(void);
2
extern void b(void);
3
4
void a(void)
5
{
6
}
7
8
static void b(void)
9
{
10
}

liefert nämlich der GCC die folgende Fehlermeldung:
:8:13: error: static declaration of ‘b’ follows non-static declaration
:2:13: note: previous declaration of ‘b’ was here

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Andreas Schweigstill schrieb:
> Das ist falsch, denn …

… dein Code ist falsch.  Wenn sich Deklaration und Definition
widersprechen, ist das natürlich ein Fehler.

Deine Deklaration für b() muss natürlich auch "static" haben (statt
"extern"), aber das "extern" bei der für a() kannst du genauso gut
weglassen – nicht mehr und nicht weniger habe ich geschrieben.

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

Jörg Wunsch schrieb:
> Andreas Schweigstill schrieb:
>> Das ist falsch, denn …
>
> … dein Code ist falsch.  Wenn sich Deklaration und Definition
> widersprechen, ist das natürlich ein Fehler.

...was aber zeigt, dass eine extern-Deklaration eben nicht immer 
überflüssig ist. Denn:

Wenn sie immer überflüssig wäre, könnte man sie immer weglassen, 
ohne dass sich was ändert.  Ist bei Anderas' Beispiel aber nicht der 
Fall.

von Yalu X. (yalu) (Moderator)


Lesenswert?

Johann L. schrieb:
> Wenn sie immer überflüssig wäre, könnte man sie immer weglassen,
> ohne dass sich was ändert.  Ist bei Anderas' Beispiel aber nicht der
> Fall.

Aber es ändert sich doch tatsächlich nichts, wenn man das "extern"
weglässt: Der Compiler liefert immer noch die gleiche Fehlermeldung.

Er stört sich ja nicht an dem "extern", sondern daran, dass die Funktion
einmal ohne und einmal mit "static" deklariert ist.

von Sebastian V. (sebi_s)


Lesenswert?

Sina Anargo schrieb:
> ich wollte "extern" richtig verstehen. Ursprünglich habe ich das von dem
> folgenden wie ich finde sehr schönen Trick:

Der Trick ist Schwachsinn. Es reicht die Funktion einfach als inline zu 
deklarieren. Funktionen sind sowieso extern, außer static Funktionen. 
Der Hauptsinn von inline ist meiner Meinung nach auch nicht den Compiler 
dazu zu bringen die Funktion zu inlinen, sondern erlaubt es Funktionen 
in Headern zu deklarieren UND zu definieren, ohne das es beim Linken 
Fehler wegen mehrfacher Definitionen gibt.

von Andreas S. (Firma: Schweigstill IT) (schweigstill) Benutzerseite


Lesenswert?

Yalu X. schrieb:
> Er stört sich ja nicht an dem "extern", sondern daran, dass die Funktion
> einmal ohne und einmal mit "static" deklariert ist.

Oh, wie peinlich... :-(((((

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Johann L. schrieb:
> ...was aber zeigt, dass eine extern-Deklaration eben nicht immer
> überflüssig ist.

Das schrob ich ja auch nicht.  Nur das Schlüsselwort "extern" ist
eben bei einer Funktionsdeklaration überflüssig (vom von A. K.
genannten, C99-spezifischen inline-Fall abgesehen).

Da in C allerdings eine Definition zugleich Deklaration ist, braucht
man eine Funktionsdeklaration (egal ob [implizit oder nicht] "extern"
oder "static") allerdings ohnehin nur dann, wenn sich zwei Funktionen
gegenseitig aufrufen können sollen, sodass es einer forward
Deklaration für eine von beiden bedarf.

von Bronco (Gast)


Lesenswert?

Jetzt muß ich aber mal ganz dumm fragen:
Wann braucht man denn dann "extern" wirklich zwingendermaßen?
Nur bei A.K.'s inline-Fall?

von Nase (Gast)


Lesenswert?

Bronco schrieb:
> Jetzt muß ich aber mal ganz dumm fragen:
> Wann braucht man denn dann "extern" wirklich zwingendermaßen?
Wenn man eine Variable aus einer anderen Übersetzungseinheit meint. Ohne 
"extern" könnte man sie andernfalls nämlich versehentlich definieren.

Auch:
A. K. schrieb:
> Das bezog sich auf den Fall:
>   file1: int variable;
>   file2: int variable = 1;
> Das in file1 ist nur dann eine Definition, wenn file2 fehlt. Mit file2
> ist es eine Deklaration.

Du solltest näher beschreiben, wo file2 fehlt: In der 
Übersetzungseinheit (#include "file2") oder beim Linken.

In file1 rutscht die variable nämlich nach .bss, in file2 wird sie eher 
in .data angelegt. Das dürfte beim Linken recht unübersichtlich werden.

von Mark B. (markbrandis)


Lesenswert?

Bronco schrieb:
> Jetzt muß ich aber mal ganz dumm fragen:
> Wann braucht man denn dann "extern" wirklich zwingendermaßen?

Man braucht es für globale Variablen, die in einer anderen 
Übersetzungseinheit definiert sind.

Zum Beispiel gibt es unter Linux die Umgebungsvariable environ. Wenn man 
die in einem eigenen Programm verwenden will, so deklariert man:
1
extern char **environ;

Hier sind noch ein paar gute Erklärungen:

http://stackoverflow.com/questions/496448/how-to-correctly-use-the-extern-keyword-in-c
http://www.geeksforgeeks.org/understanding-extern-keyword-in-c/

von Rolf M. (rmagnus)


Lesenswert?

Nase schrieb:
> Bronco schrieb:
>> Jetzt muß ich aber mal ganz dumm fragen:
>> Wann braucht man denn dann "extern" wirklich zwingendermaßen?
> Wenn man eine Variable aus einer anderen Übersetzungseinheit meint. Ohne
> "extern" könnte man sie andernfalls nämlich versehentlich definieren.

Ohne "extern" könnte es nicht nur eine Definition sein, sondern ist 
definitiv ("no pun intended") eine.
Hier ist der Unterschied zwischen Variablen und Funktionen. Bei der 
Funktion ist klar, daß es ohne den Rumpf eine Deklaration sein muss. Bei 
der Variablen gibt den nicht, also braucht man da etwas, womit man das 
explizit markieren kann.

von Markus F. (mfro)


Lesenswert?

gcc ist es völlig gleichgültig, ob man das extern bei globalen Variablen 
hinschreibt oder nicht. Der Linker zieht globale Variablen zusammen (so 
daß sie nur einmal existieren) und meckert nur dann, wenn sie mehrfach 
initialisiert werden (solange man nicht "-fno-common" vorgibt).

Aber auch wenn's der Compiler vielleicht nicht braucht: man selbst 
wird's brauchen, früher oder später...

von Steffen R. (steffen_rose)


Lesenswert?

Markus F. schrieb:
> Der Linker zieht globale Variablen zusammen

Habs oft genug beim gcc gehabt, dass er sich eine aussucht und nur einen 
Teil dorthin verlinkt. Böser Fehler.

Manchmal finde ich, dass der gcc zu tolerant ist und selbst meint, was 
richtig sein könnte. So einige Optionen sollten per default aktiv sein 
und zu einem Error statt zu einer Warnung führen. Doch das its eine 
andere Baustelle.

von Ralf G. (ralg)


Lesenswert?

Markus F. schrieb:
> gcc ist es völlig gleichgültig, ob man das extern bei globalen Variablen
> hinschreibt oder nicht.

Wenn du bei einer wirklich extern deklarierten Variablen ohne 'extern' 
keine 'error: redefinition of ...'-Meldung bekommst, hast du was falsch 
gemacht!

von Markus F. (mfro)


Lesenswert?

Ralf G. schrieb:
> Wenn du bei einer wirklich extern deklarierten Variablen ohne 'extern'
> keine 'error: redefinition of ...'-Meldung bekommst, hast du was falsch
> gemacht!

Probier's aus.

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Markus F. schrieb:
> gcc ist es völlig gleichgültig, ob man das extern bei globalen Variablen
> hinschreibt oder nicht.

Nur bei bss-Variablen.

Bei data-Variablen (initialisierte Daten) natürlich nicht.

Ralf G. schrieb:
> Wenn du bei einer wirklich extern deklarierten Variablen ohne 'extern'
> keine 'error: redefinition of ...'-Meldung bekommst, hast du was falsch
> gemacht!

Nö.  Lies' dir das C99 Rationale, Abschnitt 6.2.2 “Linkage of
Identifiers” durch.

von Ralf G. (ralg)


Lesenswert?

Vielleicht meinen wir ja verschiedene Sachen?
global.c
1
#include "global.h"
2
3
uint16_t ISR_flags; // ... oder so was ähnliches
4
5
// Code
global.h
1
#ifndef _GLOBAL_H_
2
#define _GLOBAL_H_
3
4
#define ISR_TIMER2  0x01
5
extern uint16_t ISR_flags;
6
7
#endif // _GLOBAL_H_
main.c
1
#include "global.h"
2
3
int main()
4
{
5
//
6
  return 0;
7
}
timer2.c
1
#include "global.h"
2
3
ISR(TIMER2_OVF_vect)
4
{
5
  ISR_flags |= ISR_TIMER2;
6
}

Dafür würde ich jetzt so eine 'extern'-Definition verwenden.
Wenn ich das 'extern' weglasse, gibt's Mecker vom Compiler.

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Ralf G. schrieb:
> Wenn ich das 'extern' weglasse, gibt's Mecker vom Compiler.

So?
1
$ cat global.h
2
#ifndef _GLOBAL_H_
3
#define _GLOBAL_H_
4
5
#include <stdint.h>
6
7
#define ISR_TIMER2  0x01
8
uint16_t ISR_flags;
9
10
#endif // _GLOBAL_H_
11
$ avr-gcc -Os -mmcu=atmega16 global.c main.c timer2.c -o test.elf
12
$ avr-size test.elf
13
   text    data     bss     dec     hex filename
14
    154       0       2     156      9c test.elf

Aber:
1
$ avr-gcc -Os -fno-common -mmcu=atmega16 global.c main.c timer2.c -o test.elf
2
/tmp//ccP9WlwI.o:(.bss+0x0): multiple definition of `ISR_flags'
3
/tmp//ccrZhWSF.o:(.bss+0x0): first defined here
4
/tmp//cccokVeN.o:(.bss+0x0): multiple definition of `ISR_flags'
5
/tmp//ccrZhWSF.o:(.bss+0x0): first defined here
6
collect2: error: ld returned 1 exit status

Das sind die beiden verschiedenen Linkage-Modelle, die im Rationale
erwähnt sind.  Hast du es dir denn mal angeguckt?

von Ralf G. (ralg)


Lesenswert?

Hmm, das ist bei mir hintenruntergefallen...
Ich bevorzuge diese Variante:
Jörg Wunsch schrieb:
> Aber:

Da wundert man sich dann auch nicht, falls mal ausversehen gleiche 
Variablennamen verwendet werden, dass nichts mehr funktioniert.
(Bei meinem Test heute früh hatte ich g++ eingestellt. Deswegen die 
abweichende Fehlermeldung.)

von Karl H. (kbuchegg)


Lesenswert?

Jörg Wunsch schrieb:

> Das sind die beiden verschiedenen Linkage-Modelle, die im Rationale
> erwähnt sind.  Hast du es dir denn mal angeguckt?


Ich bezieh mich auf
http://www.open-std.org/jtc1/sc22/wg14/www/C99RationaleV5.10.pdf

Dort ist zwar das Verhalten des gcc aufgeführt und fällt dort unter 
"Relaxed Ref/Def". Es wird alledings auch gesagt, dass das eine COmmon 
Extension ist die auf Unix-Linkern anzutreffen ist. Allerdings wäre das 
'not strictly conforming"

Weiters heisst es weiter unten
1
The Standard model is a combination of features of the strict ref/def
2
model and the initialization model. As in the strict ref/def model, only
3
a single translation unit contains the definition of a given object
woraus ich schliesse, dass die Duldung des gcc-Linkers von mehreren 
Definitionen nicht mehr als eben eine 'common extension" ist.

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Karl Heinz schrieb:
> Allerdings wäre das 'not strictly conforming"

Richtig: ein Programm, welches sich auf diese Variante verlässt, ist
"not strictly conforming", denn ein andere Compiler/Linker könnte ja
ein anderes Modell benutzen, auf dem das dann nicht mehr linkbar ist.

Aus heutiger Sicht wäre es auf jeden Fall schlechter Stil, sich auf
sowas zu verlassen.

von Karl H. (kbuchegg)


Lesenswert?

Jörg Wunsch schrieb:

> Aus heutiger Sicht wäre es auf jeden Fall schlechter Stil, sich auf
> sowas zu verlassen.

Seh ich auch so.
Zumal es in der Praxis kein Problem ist, die One Definition Rule 
durchzuziehen.

von Ralf G. (ralg)


Lesenswert?

Ralf G. schrieb:
> falls mal ausversehen gleiche
> Variablennamen verwendet werden, dass nichts mehr funktioniert.

Und jetzt dämmert's bei mir wieder...
Genau das hatte ich mal gemacht (und das 'static' vergessen).
Danach habe ich mich durch die ganzen Optimierungs- und 
Warneinstellungen durchgekämpft und erweitere jetzt als erstes immer die 
Liste der Compiler-/ Linkerschalter in einem neuen Projekt.
(Was ja leider nicht aus einer Voreinstellungsdatei gelesen werden 
kann.)

von Klose (Gast)


Lesenswert?

Ich empfehle folgende Vorgehensweise für Variablen/Funktionen, die 
öffentlich gemacht werden:

1.) In *.c / *.cpp Files prinzipiell kein "extern" Schlüsselwort nutzen, 
sowohl für Funktionen als auch Variablen. (Kann man wunderbar mit einem 
grep Aufruf prüfen)
1
// Modul1.c
2
int Temperature; 
3
void Measure() { <code> }

2.) In der Headerdatei, die die Schnittstelle zum Modul bildet, die 
Deklarationen dann mittels "extern".
1
// Modul1.h: Schnittstelle Modul1
2
extern int Temperature; 
3
extern void Measure();

Spart ne Menge Ärger.

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Klose schrieb:
> extern void Measure();

Nur (und das war das Thema des Threads), dass das „extern“ in diesem
Falle weiter nichts ist als ein netter Kommentar.  „void Measure();“
drückt genau dasselbe aus, und ist in C noch dazu etwas anderes als
„void Measure(void);“, was man hier besser geschrieben hätte.

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.