Forum: Mikrocontroller und Digitale Elektronik C - extern - Verständnisfrage


von Tuck I. (tuckito)


Lesenswert?

Hi zusammen,

ich bin gerade dabei ein Programm in mehrere Dateien aufzuteilen.

main.c config.h

peripherie1.c peripherie1.h

peripherie2.c peripherie2.h

Es wird vor der Kompilierung entschieden, welche Peripherie ich 
einbinde, entweder 1 oder 2.
Ich möchte nicht viele verschiedene Funktionsauffrufe verwenden.
Daher soll eine Funktion aufgerufen werden, deren Definition immer 
gleich ist, die Deklaration sich jedoch unterscheidet.
Eine Funktion mit einer Definition und einer Deklaration in 
verschiedenen Dateien zu verwenden habe ich mittlerweile hinbekommen.

Ist das in C überhaupt möglich?
Irgendwelche Tips oder wo kann ich das am besten nachlesen?

von A. S. (Gast)


Lesenswert?

Tuck I. schrieb:
> Es wird vor der Kompilierung entschieden, welche Peripherie ich
> einbinde, entweder 1 oder 2.

einbinden heisst: die Funktion aufrufen? Oder die Datei mit Kompilieren 
und Linken zu lassen?

> Ich möchte nicht viele verschiedene Funktionsauffrufe verwenden.
> Daher soll eine Funktion aufgerufen werden, deren Definition immer
> gleich ist, die Deklaration sich jedoch unterscheidet.

Was meinst Du mit Definition und Deklaration? Zumal du "extern" in den 
Betreff geschrieben hast.

Bei Variablen ist "extern int foo;" die Deklaration, "int foo;" die 
Definition.

Bei Funktionen ist kein "extern" notwendig. Trotzdem muss die Signatur 
(z.B. "int foofunc(void);" natürlich bei der Deklaration gleich sein.

> Eine Funktion mit einer Definition und einer Deklaration in
> verschiedenen Dateien zu verwenden habe ich mittlerweile hinbekommen.

Also "void foofunc(void);" in die Header-Datei, "void foofunc(void) { 
...}" in die C-Datei?

Mache bitte ein Beispiel, was unterschiedlich sein soll.

Wenn Du in beiden C-Dateien foofunc definierst, dann darfst Du nur eine 
Datei compilieren/linken.

Wenn Du Funktionspointer beherrscht, gibt es elegante Wege, 2 
Implementierungen zu haben und beide gleich zu nutzen.

von und zu (Gast)


Lesenswert?

...und warum nicht einfach mit #ifdef auseinanderhalten?

von Johannes S. (Gast)


Lesenswert?

bedingte Kompilierung? Siehe #if defined(VARIANTE_A) ... #else #if 
definded(VARIANTE_B)... #endif
Die Variante dann beim kompilieren als define mitgeben oder in einer 
header Datei definieren.

von Elektrolurch (Gast)


Lesenswert?

Da die Funktions-Deklaration in der x.h Datei ist, braucht du nur eine 
Header-Datei, wenn der Aufruf (-> Name & die Parameter) gleich sind.
Da die Definition in den .c-Dateien ist, brauchst du nur diese 
.c-Dateien auszutauschen, um andere Funktionalität zu erreichen.
Dies ist natürlich statisch und wird zur Compilezeit festgelegt.
Wenn es dynamisch sein muss, musst du unterschiedliche Namen für die 
Deklaration & Definition verwenden und mit Funktionspointern arbeiten.
Aber mein Bauchgefühl sagt mir, dass womöglich dein grundlegender Ansatz
nicht optimal ist und man das anders besser lösen kann.
Was willst du machen und warum?

von Torsten R. (Firma: Torrox.de) (torstenrobitzki)


Lesenswert?

Tuck I. schrieb:

> Ist das in C überhaupt möglich?
> Irgendwelche Tips oder wo kann ich das am besten nachlesen?

Ja, das ist möglich und in C auch nicht unüblich. Du must die 
Unterscheidung halt zur Link-Zeit machen:

Wenn Du peripheral_1 verwenden willst, dann linkst Du main.o und 
peripherie1.o zusammen. Wenn es peripheral_2 sein soll, dann eben main.o 
und peripherie2.o.

Eigentlich bräuchtest Du auch keine 2 header, wenn die Deklaration 
beider Funktions-Sätze identisch sein soll. Implementierung-Details 
würde ich in C-Dateien verschieben.

mfg Torsten

von Tuck I. (tuckito)


Lesenswert?

Danke schonmal für die Antworten. Im falschen Subforum und trotzdem so 
viele Antworten :)
Ich erkläre vielleicht nochmal ein bisl was:

A. S. schrieb:
> einbinden heisst: die Funktion aufrufen? Oder die Datei mit Kompilieren
> und Linken zu lassen?
Die Datei beim Kompilieren mit #ifdef entsprechend auswählen.

> Was meinst Du mit Definition und Deklaration? Zumal du "extern" in den
> Betreff geschrieben hast.
Definition: void tuWas(uint8_t data1);
Deklaration: void tuWas(uint_8 data1){
  ....
}
Titel etwas unglücklich gewählt...

> Also "void foofunc(void);" in die Header-Datei, "void foofunc(void) {
> ...}" in die C-Datei?
Genau, das ist eigentlich nicht schwierig :-) Ein Problem hatte ich 
zuvor mit structs die in den Funktionen anderer Dateien aufgerufe werden 
sollen. Das ging dann mit extern.

> Mache bitte ein Beispiel, was unterschiedlich sein soll.
Bsp zwei Hardwaremodule mit unterschiedlicher Anzahl 7 Segment Digits.
Die Aufbereitung der Ausgabe unterscheidet sich dann.

> Wenn Du in beiden C-Dateien foofunc definierst, dann darfst Du nur eine
> Datei compilieren/linken.
Eigentlich dachte ich, dass genau das mit #ifdef erledigt wird
Bsp:
#if PERIPHERIE == PERIPHERIE1
#include "peripherie1.h"
#elif PERIPHERIE == PERIPHERIE2
#include "peripherie2.h"
#endif
Oder macht plattformio da irgendwelche krummen Dinge?
Zumindest wird die nicht gesetzte Datei im Editor ausgegraut, also wird 
das "erkannt".
Beim Kompilieren und Linken taucht im Status immer jede Datei auf, in 
der die Funktion deklariert wird. "multiple definition of"

> Wenn Du Funktionspointer beherrscht, gibt es elegante Wege, 2
> Implementierungen zu haben und beide gleich zu nutzen.
Leider noch nicht.

und zu schrieb:
> ...und warum nicht einfach mit #ifdef auseinanderhalten?
Ich hatte zuvor eine riesige Datei mit sehr vielen #ifdef Aufrufen für 
unterschiedlich benannte Funktionen, die eigentlich das Gleiche gemacht 
hatten. Das wollte ich jezt aufdröseln.

Elektrolurch schrieb:
> Da die Funktions-Deklaration in der x.h Datei ist, braucht du nur
> eine
> Header-Datei, wenn der Aufruf (-> Name & die Parameter) gleich sind.
> Da die Definition in den .c-Dateien ist, brauchst du nur diese
> .c-Dateien auszutauschen, um andere Funktionalität zu erreichen.
> Dies ist natürlich statisch und wird zur Compilezeit festgelegt.
> Wenn es dynamisch sein muss, musst du unterschiedliche Namen für die
> Deklaration & Definition verwenden und mit Funktionspointern arbeiten.
> Aber mein Bauchgefühl sagt mir, dass womöglich dein grundlegender Ansatz
> nicht optimal ist und man das anders besser lösen kann.
> Was willst du machen und warum?

Mir schwebt gerade ein Lösung vor. Ich verwende zum einen eine 
selbstgebastelte Bibliothek für eine Siebensegmentanzeige mit 
Shiftregistern, die ich eben auslagern wollte. Dazu eine fertige 
Bibliothek für ein anderes Modul mit mehr Segmenten und auch speziellem 
Chip zur Ansteuerung, die um die dubiose Funktion erweitert wird, um die 
Ausgabe auszubereiten.
Meine Funktion zum Aufrufen ist bei beiden identisch, unterscheidet sich 
jedoch bei der genannten Aufbereitung. Möglicherweise wäre es ja besser 
diese eine Funktion im "Hauptprogramm" zu belassen und dann mit #ifdef 
zu unterscheiden, welch Aufbereitung am Zuge ist. Dann entfällt das 
ganze Gedöhns, das mir Sorgen macht und die beiden Bibliotheken bleiben 
unberührt.
main.c config.h <- hier kommt die eine Funktion hinein

peripherie1.c peripherie1.h peripherie2.c peripherie2.h <- unberührt

Möglicherweise wollte ich das umständlich kompliziert machen.

von Dirk B. (dirkb2)


Lesenswert?

Tuck I. schrieb:
>> Was meinst Du mit Definition und Deklaration? Zumal du "extern" in den
>> Betreff geschrieben hast.
> Definition: void tuWas(uint8_t data1);
> Deklaration: void tuWas(uint_8 data1){
>   ....
> }

Genau andersherum.

Eine Deklaration ist eine reine Information. Die Variable/Funktion mit 
diesen Namen gibt es und sie hat diesen Typ.

Eine Definition verbraucht Speicher. Das ist Code oder eine Variable 
wird angelegt.
In C/C++ impliziert eine Definition auch eine Deklaration.

Deklaration: void tuWas(uint8_t data1);
Definition: void tuWas(uint_8 data1){
   ....
}

Deklaration: extern int foo;
Definition: int foo;

: Bearbeitet durch User
von Tuck I. (tuckito)


Lesenswert?

Sorry du hast recht, das kommt davon wenn man pennt. Da ist mir jetzt 
peinlich.

von A. S. (Gast)


Lesenswert?

Tuck I. schrieb:
> Eigentlich dachte ich, dass genau das mit #ifdef erledigt wird
> Bsp:
> #if PERIPHERIE == PERIPHERIE1
> #include "peripherie1.h"
> #elif PERIPHERIE == PERIPHERIE2
> #include "peripherie2.h"
> #endif
> Oder macht plattformio da irgendwelche krummen Dinge?
> Zumindest wird die nicht gesetzte Datei im Editor ausgegraut, also wird
> das "erkannt".
> Beim Kompilieren und Linken taucht im Status immer jede Datei auf, in
> der die Funktion deklariert wird. "multiple definition of"

Das entfernt oder inkludiert nur die Header-Datei (.h).

Es bleiben jedoch beide C-Dateien im Projekt (und das soll auch so 
sein).

Ein einfacher Hack ist, in peripherie1.h

#define TuWas(a) TuWas1(a)

zu schreiben und in peripherie2.h

define TuWas(a) TuWas2(a)

Und dann entsprechend TuWas1 und 2 in peripherie1.c und 2.c zu 
schreiben.


Mit Funktionspointern läuft das ähnlich, nur typsicherer. #define-Gräber 
sind verlockend und verwirrend.


Die zweite Möglichkeit: In der C-Datei eine ähnliche #define-Klammer 
über den ganzen Code. Beispiel für peripherie1.c, 2.c ist analog 
gegengesetzt:
1
#if PERIPHERIE==PERIPHERIE1
2
.....
3
void TuWas(int data)
4
{
5
   ....
6
}
7
#else
8
static int dummy;  /* damit irgendwas drin ist, sonst meckert der Compiler evt. */
9
#endif

von Tuck I. (tuckito)


Lesenswert?

A. S. schrieb:
> Das entfernt oder inkludiert nur die Header-Datei (.h).
Again what learned.
> Mit Funktionspointern läuft das ähnlich, nur typsicherer. #define-Gräber
> sind verlockend und verwirrend.
Pointer werde ich als nächstes angehen.

> Die zweite Möglichkeit: In der C-Datei eine ähnliche #define-Klammer
> über den ganzen Code. Beispiel für peripherie1.c, 2.c ist analog
> gegengesetzt:
> #if PERIPHERIE==PERIPHERIE1
> .....
> void TuWas(int data)
> {
>    ....
> }
> #else
> static int dummy;  /* damit irgendwas drin ist, sonst meckert der
> Compiler evt. */
> #endif

Genau so habe ich das jetzt umgesetzt!
Funktioniert wunderbar.

von Marc P. (marcvonwindscooting)


Lesenswert?

Tuck I. schrieb:
> Hi zusammen,
>
> ich bin gerade dabei ein Programm in mehrere Dateien aufzuteilen.

Und in der schliesslich gewaehlten Variante wird wieder mit 
Praeprozessortricks Teile aus dem Source code selektiert??

BEOBACHTUNG: Das ist fast das Gegenteil des urspruenglichen Ansatzes!

Sprich: der Source Code tut was anderes, je nachdem welches #define 
gesetzt wurde. Unschoen.
Ja ich mach solche Sachen auch. Aber bloss, wenn ich tatsaechlich static 
inline (Tuck I. - schau dir das jetzt bitte noch nicht an .-) Funktionen 
unterschiedlich haben will.

> Es wird vor der Kompilierung entschieden, welche Peripherie ich
> einbinde, entweder 1 oder 2.
Wie entscheidest Du? Wo wird das hinterlegt? In config.h? In einer 
Datei, welche das compilieren/linken regelt, wie Makefile oder sowas?
Wenn Makefile, definierst Du dann gleich die Ziele 'peripherie1' UND 
'peripherie2', damit du nicht wieder im Source-Code rumaendern musst 
(ich waere entschieden dafuer).

Der Zeitpunkt der Enscheidung kann uebrigens auch erst zu Link-Zeit 
sein, wenn Du eine andere Vorgehensweise waehlst, wie z.B. Makefile mit 
unterschiedlichen Zielen.

> Ich möchte nicht viele verschiedene Funktionsauffrufe verwenden.
Vorbildlich.

Huete dich vor 'einfachsten' Loesungen. Du warst selber auf dem besten 
Weg eine sehr saubere und klare Loesung zu finden und nun hast Du dich 
von #Paeprozessor-Tricks verlocken (versauen!) lassen.
Wenn Du noch einen Schritt weiter gehst, von dem getrennten .c-Dateien 
(und daraus erzeugten .o/.obj-Dateien) zu (statischen) Bibliotheken, 
dann wirst Du mit dem #if...#else... ganz schoen auf dem Bauch landen. 
Weil der Name der Objektdatei dannn nicht mehr eindeutig deren 
Funktionalitaet zuzuordnen ist. Stichwort 'Etikettenschwindel'.

von tuckito (Gast)


Lesenswert?

Was ist denn dann die sauberste Lösung für richtige Trennung bzw wo kann 
man sowas nachlesen? C Cookbook?
Diverse Tutorials zeigen entweder Präprozessortricks oder gar keine 
gleichnamige Funktion. Weil das niemand so macht wie ich mir das 
vorstelle?
Nimmt man die hier schonmal genannten Funktionszeiger?
Ist eine Makefileverbiegung nicht auch ein Schritt zur Unübersichtlich?
Tausend Fragen eines verwirrten Bastlers.

von Marc P. (marcvonwindscooting)


Lesenswert?

Funktionszeiger - nein dafuer nicht noetig.

Es kommt auf deine Entwicklungsumgebung an.
Hast Du 'ne IDE die dir jeden (Standard-)Wunsch von den Augen abliest?
Oder machst Du was auf der Kommandozeile? Oder hast Du 'ne IDE aber 
darfst wenigstens noch deine Makefiles selber schreiben?

Zum Verstehen sollte man meiner Meinung nach ein  paar mal seine 
Programme selbst  'bauen' (hier am Beispiel von Linux/*nix mit gcc - ich 
kann nichts anderes): ein oder mehrere .c-Files 'compilieren' zu .o ; 
mehrere .o zu einer ausfuehrbaren Datei 'linken' evtl. unter 
Zuhilfenahme von Bibliotheken .a

Schau mal da:
https://www.cs.utah.edu/~zachary/isp/tutorials/separate/separate.html

Das mit den gleichnamigen Funktionen ist nicht so wichtig. Bei dem was 
du naemlich am Ende zusammenlinkst, da darf es eh keine gleichnamigen 
Funktionen geben, sonst gibt es Fehler beim Linken. Du musst naemlich 
spaetestens beim Linken auswaehlen, welches Objektfile (.o) zu verwenden 
willst. Der Linker sieht nur was du ihm uebergibst.Getrennt Kompilierung 
(mehrere .c) ist schon das was du suchst.
Was dir noch fehlt, ist: wie wir aus deinen mehrdeutigen Quellen eine 
gueltige ausfuehrbare Datei. Manche Menschen machen das mit 'make' und 
seinen Makefiles. Manchmal mit expliziten Shell-Scripten. Manchmal 
explizit auf der Kommandozeile. Manchmal mit Programmen, die Makefiles 
generieren.

Benutzt Du eine IDE, dann kann es sein, dass die einfach alle Dateien 
ins ausfuehrbare Programm stecken will und das geht dann eben schief, 
mangels Selektion. Mit IDEs kenn ich mich nicht aus. Seit 15+ Jahren 
keine mehr verwendet...


PS: Makefile wird nicht verbogen, sondern einmal sagst Du z.B.

make peripherie1

das andere Mal

make peripherie2

Du aenderst keine Datei, du modifizierst keine Umgebungsvariable oder 
so. Du sagst, welche Variante du (genau jetzt) willst.

: Bearbeitet durch User
von A. S. (Gast)


Lesenswert?

tuckito schrieb:
> Ist eine Makefileverbiegung nicht auch ein Schritt zur Unübersichtlich?

Ja. Du bist nach eigenen Angaben ein Anfänger. Und bevor Du anfängst, 
Makefiles zu verbiegen, solltest Du erstmal innerhalb des Sourcecodes 
Erfahrungen sammeln. Und ein Makefile erstmal für typische Dinge 
kennenlernen.

Dein Weg mit der #ifdef-Klammer um den Sourcecode ist bislang der 
einfachste.

Ja, wenn Du eigene Bibliotheken erstellst, geht das so nicht. Aber das 
ist unwichtig, solange Du die genauen Mechanismen von includierten 
Dateien, extern oder Funktionspointer noch nicht durchdrungen hast.

@Marc P: Wenn jemand erste Erfahrungen sammelt, dann ist es m.E. wenig 
sinnvoll, Alle Register (Make, eigene Bibliotheken, manuelles Linken, 
...) zu ziehen. Irgendwann kann keiner mehr ein Hallo-Welt ausprobieren, 
wenn er nicht den Startup-Code und das Linker-Skriptfile sauber für 
beliebige noch unbekannte Plattformen erstellt hat.

Ja, man kann das Tayloring ins Makefile legen, aber alles zu seiner 
Zeit.

von MaWin (Gast)


Lesenswert?

A. S. schrieb:
> Ja, wenn Du eigene Bibliotheken erstellst, geht das so nicht.

Warum nicht? Was passiert, wenn ich mehrere Libs mit gleichnamigen 
Funktionen einbinde. Und zu guter letzt noch eine .o mit einer 
gleichnamigen Funktion? ;->>>

von MaWin (Gast)


Lesenswert?

oder erst die .o Datei und dann die Libs mit gleichnamigen Funktionen? 
;->>>

von A. S. (Gast)


Lesenswert?

MaWin schrieb:
> Warum nicht? Was passiert, wenn ich mehrere Libs mit gleichnamigen
> Funktionen einbinde. Und zu guter letzt noch eine .o mit einer
> gleichnamigen Funktion? ;->>>

Dafür brauchst Du wieder einen Schritt: Für einen Anfänger, der im 
Ausgangspost die Wirkungsweise von #Include noch nicht verstanden hat, 
ist es ein Weiter weg, bis er sicherstellen kann, dass seine libs mit 
Übersetzungs-Einheiten gleicher Funktionsnamen in der notwendigen 
Reihenfolge angezogen werden.

Nur zum Verständnis: Er muss nicht nur wissen, dass der Linker sich aus 
den Bibliotheken all das raus saugt, was er braucht, dass bei 2 oder 
mehr gleichen Funktionsnamen nur eine der Übersetzungseinheiten 
angezogen werden darf, nein, er muss auch noch die Reihenfolge mit ein 
paar Makefile-Hacks beherrschen. Ich bin mir nichtmal sicher, ob in C 
definiert ist, wann welches Symbol erstmals in den Bibliotheken gesucht 
wird...

von Marc P. (marcvonwindscooting)


Lesenswert?

A. S. schrieb:
> Ja, man kann das Tayloring ins Makefile legen, aber alles zu seiner
> Zeit.

100% Zustimmung.
Ich hoffe, ich habe auch nicht dazu geraten Makefiles zu schreiben, 
sondern nur kurz und oberflaechlich sagen, was 'man' so machen kann. Ich 
bin selber von Makefiles abgekommen, ausser bei Standard-Sachen.

Das manuelle Linken, das finde ich schon wichtig. Zumal Tuck I. ja schon 
mehr will als ein Anfaenger. Und er will offensichtlich verstehen.

@MaWin
> oder erst die .o Datei und dann die Libs mit gleichnamigen Funktionen?

Ja. Oder gar 'weak references' (als default-Implementierung) und bei 
Bedarf mit einer gleichnamigen Funktion aus der .o 'ueberschreiben'...
So mach ich das bei den Interrupt-Handlern (an festen Adressen) auf'm 
ARM. Ist aber schon ein bissl haarig und ich bin nicht so gluecklich 
damit. (Tippfehler => keine Meldung von Compiler oder Linker, aber nix 
funktioniert ):

von Einer K. (Gast)


Lesenswert?

Tuck I. schrieb:
> Ist das in C überhaupt möglich?
Ja, ich würde mal sagen, dass du hier auf eine C Schwäche gestoßen bist.
Klar bekommt man das auch in C irgendwie hingefummelt....
Aber wirklich schön wird das nicht


C++ bietet mehr Möglichkeiten gleichnamige Funktionen/Methoden unter zu 
bringen.
Ganz ohne define Klimmzüge.
z.B namespaces, Klassen

Gibts einen besonderen Grund, warum du mit C startest, und nicht mit 
C++?
Denn später irgendwann, ist der Umstieg von C++ zu C leichter, als der 
von C zu C++.

Beispiel:
1
namespace peripherie1
2
{
3
  void tuwas()
4
  {
5
    // tue dieses
6
  }
7
}
8
9
namespace peripherie2
10
{
11
  void tuwas()
12
  {
13
    // tue was anderes
14
  }
15
}
16
17
// hier wähle welches tuwas() zum default wird
18
//using namespace peripherie1;
19
using namespace peripherie2;
20
21
int main() 
22
{
23
  tuwas(); // using bestimmt welches tuwas
24
  peripherie1::tuwas();
25
  peripherie2::tuwas();
26
  while(1);
27
}

von Torsten R. (Firma: Torrox.de) (torstenrobitzki)


Lesenswert?

Arduino Fanboy D. schrieb:
> Ganz ohne define Klimmzüge.

echt? Wie bekommst Du den das "richtige" `using namespace` in den Code?

von A. S. (Gast)


Lesenswert?

Torsten R. schrieb:
> echt? Wie bekommst Du den das "richtige" using namespace in den Code?

Kannst Du dort sehen: mit sorgfältigen auskommentieren :-)

von Wech (Gast)


Lesenswert?

was ist der fanbox nur für ein typ
laber von cpp obwol nur cgefragt

Macht den wech

von Torsten R. (Firma: Torrox.de) (torstenrobitzki)


Lesenswert?

Wech schrieb:
> was ist der fanbox nur für ein typ
> laber von cpp obwol nur cgefragt

Was ist den daran so schlimm, wenn mal jemand ein Lösung zeigt, die über 
dem Tellerrand liegt?

von Tuck I. (tuckito)


Lesenswert?

Naja so verkehrt ist es ja nicht.
Ich hatte auch schon damit geliebäugelt.
Nur dieses Mainstream unelitäre "Arduino c/c++ Gewurschtel" will ich 
nicht verwenden :-)

von Einer K. (Gast)


Lesenswert?

Torsten R. schrieb:
> Was ist den daran so schlimm, wenn mal jemand ein Lösung zeigt, die über
> dem Tellerrand liegt?

Ich danke dir für die Blumen!

Aber lass bitte den "xxx" men laufen, der stalkt mich schon eine kleine 
Weile. Wird aber auf Grund seiner Defizite, den Arsch nicht in die Hose 
bekommen.

von Einer K. (Gast)


Lesenswert?

Tuck I. schrieb:
> Nur dieses Mainstream unelitäre "Arduino c/c++ Gewurschtel" will ich
> nicht verwenden :-)

Vorurteile!

C++ ist vielleicht/oberflächlich etwas komplizierter, als C, aber kein 
"Gewurstel".

von tuckito (Gast)


Lesenswert?

Das war ein Spaß! Ich möchte nur kein hipper Programierer sein, der 
Makerheftchen kauft. Ist ja fast so wie damals als manche in die 
Bücherei gingen um C64 Bücher mit fertigen Projekten auszuleihen.

PS: ebenfalls Spaß

von Einer K. (Gast)


Lesenswert?

Eine Person, ein Nick, so erfordert es die Forenregel.

von Veit D. (devil-elec)


Lesenswert?

Hallo,

wenn ich zu den namespace nochwas sagen darf. Ich würde dann aber dafür 
sorgen den namespace nicht global zur Verfügung zu stellen. Ansonsten 
ist der Sinn dahinter wirklungslos. Will sagen das namespace zwar viel 
möglich macht, aber auch kein Allheilmittel ist. Ansonsten bemerkt man 
das Problem erst später was man ohne sofort bemerkt hätte.

von Einer K. (Gast)


Lesenswert?

Veit D. schrieb:
> Hallo,
>
> wenn ich zu den namespace nochwas sagen darf. Ich würde dann aber dafür
> sorgen den namespace nicht global zur Verfügung zu stellen. Ansonsten
> ist der Sinn dahinter wirklungslos. Will sagen das namespace zwar viel
> möglich macht, aber auch kein Allheilmittel ist. Ansonsten bemerkt man
> das Problem erst später was man ohne sofort bemerkt hätte.

Na...
Hier ist der Zweck zwischen zwei Konfigurationen zu wählen.
Und das tut man eben, am besten, nur an einer Stelle.

Nicht an tausend Stellen im Code, per #define, #indef usw., wenn man es 
denn vermeiden kann.

Wie würdest du das denn lösen?

von Veit D. (devil-elec)


Lesenswert?

Hallo,

ehrlich gesagt würde ich in dem Bsp. gar keinen globalen namespace 
anbieten. Sondern nur mit Bereichsnamen arbeiten. Sonst weiß man 
irgendwann nicht mehr aus welchen namespace "default" kommt. Weil der 
Blick darauf irgendwann schwindet. Meine Meinung.

Meine Hardware Libs mit Klassen sind so aufgebaut das ich global keinen 
namespace freigeben muss. Intern arbeite ich mit anonymen namespace und 
mit Bereichsnamen wenn etwas woandersher inkludiert/benötigt wird. Damit 
habe ich global im Hauptprogramm nur mit Klassennamen und deren 
Methodenname zu tun und die verschiedensten Libs können dennoch gleich 
aufgebaut sein mit gleichen struct Bezeichner usw.

Als ich das noch nicht so hatte kam es darauf an in welcher Reihenfolge 
ich den namespace zur Verfügung gestellt und Libs inkludiert habe, 
einmal kompilierte es, einmal knallte es. Das ist der Grund warum ich 
vor globaler namespace Freigabe etwas warnen möchte. Man kann sich 
leicht drin verstricken und wundert sich warum es trotz namespace 
Kapselung nicht kompiliert.

von Einer K. (Gast)


Lesenswert?

Veit D. schrieb:
> ehrlich gesagt würde ich in dem Bsp. gar keinen globalen namespace
> anbieten. Sondern nur mit Bereichsnamen arbeiten.

Tut mir leid, aber den Begriff "Bereichsnamen" kann ich nicht in der C++ 
Spezifikation und auch nicht bei den OOP Design Patern finden.

Eigentlich müsste ich dich ja jetzt fragen, was du damit meinst.
Aber damit müsste ich ja auch vor mir selber eingestehen, dass ich das 
nicht weiß.
Gerade in diesem Forum, eine Schwäche zugeben?
Nee, dafür bin ich zu feige.

von Veit D. (devil-elec)


Lesenswert?

Hallo,

um bei dem Bsp. zu bleiben. Wenn :: der Bereichsoperator ist, dann ist 
der Name davor für mich der Bereichsname. In dem Fall peripherie1 und 
peripherie2.
Man kann es auch anders herleiten. namespace kapselt einen Code-Bereich. 
Den Namen vom namespace kann man in meinen Augen deswegen auch als 
Bereichsnamen betiteln. Sollte nicht sooo falsch sein. Vielleicht ist es 
auch einfach alles nur zu viel deutsch. :-)  Um dir ein Brücke zu bauen.
1
...
2
...
3
int main() 
4
{
5
  tuwas(); // using bestimmt welches tuwas
6
  peripherie1::tuwas();
7
  peripherie2::tuwas();
8
  while(1);
9
}

von Einer K. (Gast)


Lesenswert?

Veit D. schrieb:
> Wenn :: der Bereichsoperator ist, dann ist
> der Name davor für mich der Bereichsname.

Danke!
"Eine" Definition ist besser, als "keine"

Veit D. schrieb:
> ehrlich gesagt würde ich in dem Bsp. gar keinen globalen namespace
> anbieten. Sondern nur mit Bereichsnamen arbeiten. Sonst weiß man
> irgendwann nicht mehr aus welchen namespace "default" kommt. Weil der
> Blick darauf irgendwann schwindet. Meine Meinung.

Dann muss ich nochmal nachfragen:
Wie würdest du eine globale Bereichsumschaltung machen, ohne einen der 
"Bereiche" mit using zuzuordnen?

Verstehe mich bitte richtig.
Ich möchte dich nicht kritisieren, nur deine Kritik/Vorschlag verstehen.

von Veit D. (devil-elec)


Lesenswert?

Hallo,

man könnte sich irgendwas mit Klassen und Parameterübergabe für die 
Initialisierung ausdenken. Nur hilft das dem TO nicht weiter. C++ kommt 
ja nur voll zum tragen wenn man verschiedene Objekte mit 
unterschiedlichen Methoden aber gleichen Methodennamen anlegen möchte 
usw.. Das alles benötigt der TO nicht. Wenn ich mir den Eingangspost 
durchlese möchte der TO nur stumpf vorgeben welches Headerfile 
eingebunden werden soll. Dafür halte ich die Auswahl aus
1
// #include <peripherie1.h>
2
// #include <peripherie2.h>

mit auskommentieren für völlig ausreichend. Man benötigt weder define 
noch namespace. Alles was man so drumherum bauen könnte hat hier keinen 
echten Nutzen, wenn man das einmal ganz nüchtern betrachtet. Und weil 
der TO C und nicht C++ programmiert hat sich das sowieso erledigt. Wir 
würden mit C++ bestimmt seine Peripherie Klassenfein aufsplitten mit 
allen drum und dran und am Ende, um bei TO Aufgabe zu bleiben, im 
Hauptprogramm auch nur eine Klasse für alle Objekte verwenden. Bedeutet 
großer Aufwand ohne Nutzen. Erst wenn verschiedene Klassen für 
verschiedene Objekte gemeinsam Verwendung finden sollen sind wir mit C++ 
klar im Vorteil. Genau das sehe ich hier nicht.

von Einer K. (Gast)


Lesenswert?

Veit D. schrieb:
> Dafür halte ich die Auswahl aus
> // #include <peripherie1.h>
> // #include <peripherie2.h>
>
> mit auskommentieren für völlig ausreichend.

Nein, das ist es nicht.
Denn dafür müsste zusätzlich das makefile geändert werden.
Sofern überhaupt eins verwendet wird.
Und damit hat man schon min 2 Schrauben an denen gedreht werden muss.

Bedenke:
Es gibt ja auch noch *.c oder eben *.cpp Dateien, neben den *.h
Und doppelte Definitionen mag der Linker nun gar nicht.

von Veit D. (devil-elec)


Lesenswert?

Hallo,

na jetzt bin ich wirklich verwundert, weil ich das Problem noch nie 
hatte, dass Lib Dateien angefasst werden die gar nicht inkludiert werden 
sollen. Ich habe das gerade ausprobiert.
Wenn
test1.h und test1.cpp
neben
test2.h und test2.cpp

mit gleichen Inhalt (internes include x.h natürlich geändert) existieren 
aber nur test1.h inkludiert werden soll, dass es dann überhaupt ein 
Problem gibt. Wäre mir nie in den Sinn gekommen. Ehrlich gesagt finde 
ich das Verhalten schon etwas merkwürdig.

von Einer K. (Gast)


Lesenswert?

Veit D. schrieb:
> Ehrlich gesagt finde
> ich das Verhalten schon etwas merkwürdig.
Ich nicht.

Jede *.c, *.cpp und auch *.S Datei ist eine eigene Übersetzungseinheit.
Irgendwelche *.h, oder welche du davon auswählst, interessiert den 
Compiler eigentlich überhaupt nicht.
Die *.h bekommt er nicht zu sehen, denn der Präprozessor bindet diese in 
den Code ein und der ist eben vor dem eigentlichen Compiler dran.

Veit D. schrieb:
> Wäre mir nie in den Sinn gekommen.
Siehste, so kannste auch vom dööfsten noch was lernen.

von A. S. (Gast)


Lesenswert?

Veit D. schrieb:
> Dafür halte ich die Auswahl aus
> // #include <peripherie1.h>
> // #include <peripherie2.h>
>
> mit auskommentieren für völlig ausreichend

Das ist nicht das Problem des TO.

Dem TO reicht ein include (auch wenn er es vorher fälschlicherweise mit 
2 versucht hat) und 2 ifdefs. Alternativ funktionsptr oder defines oder 
oder.

Eure Diskussion geht aber am Problem des TO vorbei.

von Einer K. (Gast)


Lesenswert?

A. S. schrieb:
> und 2 ifdefs. Alternativ funktionsptr oder defines oder
> oder.

Mantra:
> Jedes vermiedene Präprozessor Konstrukt ist ein gutes Konstrukt
> Jedes vermeidbare Präprozessor Konstrukt ist ein böses Konstrukt

Und Pointer belegen, in der Regel, Ram.
Auch das ist vermeidbar.

A. S. schrieb:
> Eure Diskussion geht aber am Problem des TO vorbei.
Ja?
Darum sagte er sicherlich auch:

Tuck I. schrieb:
> Naja so verkehrt ist es ja nicht.
> Ich hatte auch schon damit geliebäugelt.

Und zudem hats ja einen Sachverhalt beim  Veit D.(devil-elec) geklärt. 
Was ja irgendwie auch ein positiver Effekt der Diskussion ist.

von A. S. (Gast)


Lesenswert?

Arduino Fanboy D. schrieb:
> Mantra:
>> Jedes vermiedene Präprozessor Konstrukt ist ein gutes Konstrukt
>> Jedes vermeidbare Präprozessor Konstrukt ist ein böses Konstrukt

Aber Dein ein- und auskommentieren ist besser?

von Veit D. (devil-elec)


Lesenswert?

Hallo,

warum geht unsere Diskussion am Problem des TO vorbei? Er hat doch das 
Problem das er nicht weiß wie er das sauber je nach Bedarf inkludieren 
soll. Dabei dachte ich etwas naiv ich könnte helfen und verstehe jetzt 
das Problem des TO besser. Nämlich das es nicht so einfach ist.

Wegen meiner Verwunderung nochmal. Wenn der Präprozessor beginnt und nur 
peripherie1.h inkludieren soll, warum wird dann eine peripherie2.h mit 
ihrem .c überhaupt angefasst und übersetzt? Letzteres peripherie2.h 
include bleibt ja auskommentiert. Werden wirklich immer alle "Dateien" 
übersetzt die so rumliegen obwohl sie gar nicht verwendet werden? Kann 
doch nicht sein.

von MaWin (Gast)


Lesenswert?

Veit D. schrieb:
> Wenn der Präprozessor beginnt und nur
> peripherie1.h inkludieren soll, warum wird dann eine peripherie2.h mit
> ihrem .c überhaupt angefasst und übersetzt?

Weil das egal ist. Die Frage ist nicht, was included oder übersetzt 
wird, sondern was der Linker versucht einzubinden.
Ein compiliertes C Programm kann keine Maschine ausfüren. ;-)

von Veit D. (devil-elec)


Lesenswert?

Hallo,

tut mir leid, ich habs noch nicht verstanden. Ich kann meine Frage auch 
umformulieren und überspitzen. Wenn der Linker sowieso macht was er 
will, warum benötigt man dann überhaupt die include Direktive in der 
main.c? Mit include lege ich doch fest was eingebunden werden soll und 
was nicht.

von MaWin (Gast)


Lesenswert?

Durch ein #include wird der Text der angegebenen Datei einfach genau an 
dieser Stelle eingefügt (so etwa wie 'copy paste').

Aus einem C file baut der Compiler ein object file. Das ist quasi der 
Maschinencode für das gewählte Target.

Aber die Abhängigkeiten zwischen den Modulen wurde noch nicht 
hergestellt bzw. geprüft. Und es fehlt noch das mapping auf den 
Speicher. Darum kümmert sich der Linker.

https://www.informatik.uni-leipzig.de/~meiler/Propaed.dir/PropaedWS12.dir/Vorlesung.dir/V08-Dateien/image002.gif

Das solltest du nachlesen und verstehen.

von Einer K. (Gast)


Lesenswert?

A. S. schrieb:
> Arduino Fanboy D. schrieb:
>> Mantra:
>>> Jedes vermiedene Präprozessor Konstrukt ist ein gutes Konstrukt
>>> Jedes vermeidbare Präprozessor Konstrukt ist ein böses Konstrukt
>
> Aber Dein ein- und auskommentieren ist besser?

Natürlich!
Weil das in nur einer einzigen Zeile des Projektes passieren kann/muss.
Du benötigst mehrere Zeilen mit Präprozessor Gedönse.
Evtl. auch eine makefile Anpassung.
Und beim Wechsel der Konfiguration gar ein "make clean" oder die IDE 
übliche Entsprechung

Zudem, falls es dir nicht aufgefallen ist, dann lass dich mit der Nase 
drauf stoßen:
Das Mantra hat eine Hysterese!
Und zwar die, in der die unvermeidbaren Präprozessor Konstrukte stecken.

Veit D. schrieb:
> Wegen meiner Verwunderung nochmal. Wenn der Präprozessor beginnt und nur
> peripherie1.h inkludieren soll, warum wird dann eine peripherie2.h mit
> ihrem .c überhaupt angefasst und übersetzt? Letzteres peripherie2.h
> include bleibt ja auskommentiert.
Du reitest weiter auf *.h rum...
Das ist nicht zielführend.
Die Übersetzungseinheiten sind *.c und *.cpp und auch *.S Dateien.
Das hat alles nichts mit *.h Dateien zu tun.
Da kannst du auskommentieren, was du willst.
Das ist eine ganz andere Baustelle.

In der Regel schnappt sich eine IDE, fast egal welche, wenn du auf 
"Build" drückst, alle übersetzbaren Einheiten und kompiliert diese.
Und das sind eben nicht die *.h, wie du es gerne hättest, sondern die 
*.c und *.cpp und auch *.S Dateien welche dem Projekt zugeordnet sind.

von Gnorm (Gast)


Lesenswert?

Der letzte Absatz ist der springende Punkt. Wenn man nur in der Konsole 
arbeitet, tritt das beschriebene Problem nicht auf. Da wird nur exakt 
das ausgeführt, was man eingibt.

von A. S. (Gast)


Lesenswert?

Gnorm schrieb:
> Wenn man nur in der Konsole
> arbeitet, tritt das beschriebene Problem nicht auf. Da wird nur exakt
> das ausgeführt, was man eingibt.

Das hat auch mit Konsole nichts zu tun. Es sind einfach zwei Bereiche, 
die der TO zu Beginn und Veit D. zuletzt durcheinander werfen:

In einer C-Datei steht nur drin, was darin steht. Egal ob direkt oder 
per #include. Das ist nur plain Text. Keine Bibliotheken, keine 
zugehörigen .c-oder .sonstwas-Dateien.

Jede C-Datei wird allein übersetzt.

Der Linker macht aus vielen übersetzten Einheiten ein Programm. Hier aus 
den compilierten Dateien main.c, peripherie1.c und peripherie2.c und 
noch aus vielen anderen .C und Assembler-Dateien, wo z.B. Startup und 
printf oder so drin sind.

von Veit D. (devil-elec)


Lesenswert?

Hallo,

danke für eure Erklärungen. Mir war nicht bewusst, dass sich die 
Toolchain wirklich allen erreichbaren Quellcode schnappt und übersetzt. 
Damit sind wir wieder bei meiner Verwunderung. Wenn ich ganz tief 
nachdenke, ist mir immer noch nicht klar warum das überhaupt so pauschal 
alles übersetzt wird obwohl es nicht benötigt wird, weil es vom 
Programmierer nicht inkludiert wurde. Und das der Linker alle 
Objektfiles zusammenwirft kann ich wirklich noch nicht ganz glauben. 
Denn wenn man sich ein disassemblierten Quellcode anschaut findet man 
keine Codeteile die nicht reingehören. Das heißt für mich der weiß am 
Ende schon was benötigt wird und was nicht. Er prüft das nur in der 
falschen Reihenfolge. Er könnte sich demzufolge schon vorher 
Übersetzungsarbeit sparen. Soweit zu meiner Logik.

von Einer K. (Gast)


Lesenswert?

Ich sehe schon, du benötigst noch einen kräftigen Schuss aus der 
Blickwinkelkanone.
Sollst du bekommen!
(nur noch nicht in dieser Minute)

von Oliver S. (oliverso)


Lesenswert?

Veit D. schrieb:
> danke für eure Erklärungen. Mir war nicht bewusst, dass sich die
> Toolchain wirklich allen erreichbaren Quellcode schnappt und übersetzt.

Eine toolchain tut von sich aus gar nichts. Und auch eine IDE nicht.

Beide tun immer nur genau das, was jemand definiert. Wenn das nicht das 
ist, was erwartet wird, sitzt die Ursache dafür vor dem Rechner.

Oliver

von A. S. (Gast)


Lesenswert?

Veit D. schrieb:
> Und das der Linker alle
> Objektfiles zusammenwirft kann ich wirklich noch nicht ganz glauben.

Der Linker nimmt
A) Alle Objectifles, die ihm direkt übergeben werden (*), meist aus 
C-Files oder Assembler, die Du für Dein Projekt auswählst

B) Nur die Objectfiles aus den Bibliotheken (*), die Symbole enthalten, 
die noch fehlen. Z.B. ein printf, wenn es nicht A ist. Er bindet dann 
jeweils das ganze Objectfile ein, also alles, was im zugehörigen C-File 
stand. Darum hat ein abs.c gefühlt eine Zeile Code und steht nicht mit 
10 anderen Funktionen in einer Datei.

C) Manchmal ein paar implizite Dinge wie z.B. Startup-Code oder 
Dos-Umgebung oder so

Die Toolchain "schnappt" sich nichts. Für die meisten spielt sich das 
nur im "unbekannten Makefile" ab. Ganz sicher aber bindet ein "include 
<X.h>" nichts von X.c ein.

(*) Meist von Dir im Makefile oder in einer Batchdatei angegeben.

von Einer K. (Gast)


Lesenswert?

Veit D. schrieb:
> ist mir immer noch nicht klar warum das überhaupt so pauschal
> alles übersetzt wird obwohl es nicht benötigt wird, weil es vom
> Programmierer nicht inkludiert wurde.

Hier ist dein Gedankenfehler!

Du includierst nur *.h Dateien.
Die löst der Präprozessor auf, bevor der Compiler los läuft.
Der Compiler bekommt nur die modifizierten *.c und *.cpp zu sehen.

Und genau an der Stelle ist dein Satz:
> weil es vom Programmierer nicht inkludiert wurde.
Falsch!
Denn du includierst ja keine *.c oder *.cpp Dateien.
Niemals!
... nehme ich mal ganz stark an ...

Angenommen, in der main.cpp findet sich dieses
#include "test1.h"
#include "test2.h"

Und du nimmst einen weg:
//#include "test1.h"
#include "test2.h"
Das kannst du tun, macht manchmal Sinn...
Diese Änderung hat erstmal ausschließlich Auswirkungen auf die erzeugte 
main.o
Aber irgendwann übersetzt der Compiler ja die test1.c und der bekommt 
von deiner Änderung nix mit.
Denn die test1.c ist ein eigenständiger Übersetzungsvorgang.
Solange test1.c deinem Projekt zugeordnet ist, wird sie übersetzt.
Änderungen in der main.c haben darauf keine Auswirkungen.

Mit anderen Worten:
main.c und test1.c sind zwei völlig unterschiedliche 
Übersetzungseinheiten!
Zwischen diesen beiden Übersetzungsvorgängen gibt es keine Art von 
Kommunikation.
Darum können die auch an verschiedenen Ecken der Welt vorgenommen 
werden.

Veit D. schrieb:
> Und das der Linker alle
> Objektfiles zusammenwirft kann ich wirklich noch nicht ganz glauben.
> Denn wenn man sich ein disassemblierten Quellcode anschaut findet man
> keine Codeteile die nicht reingehören.
Ja klar!
Der Linker hat ein Regelwerk, anhand er das fertige Programm zusammen 
flickt. Er bekommt eine Latte an *.o *.a, oder was auch immer, vor die 
Füße geworfen.
Und hier bekommt er eben beide zu sehen!
Die test1.o und die test2.o, egal, was du in main.cpp angestellt hast.


Unter anderen führt er Referenzzähler o.ä. mit.
Wichtig ist ihm die *.o, wo die main() liegt.
Er bindet in den fertigen Code nur die *.o ein, wo mindestens 1 
"Objekt/Element" aus der main.o heraus referenziert wird.

Dafür ist das Arduino Serial ein gutes Beispiel!
Angenommen: UNO Programm, ohne Serial.
In den IDE Meldungen siehst du klar, dass der Compiler 
HardwareSerial.cpp anfasst.
Schaust du aber in den erzeugten Code, sieht man nix von Serial.
Noch nicht mal die ISR.
Machst du aber nur ein Serial.begin(9600); dann wird auch die ISR 
etabliert.
Alles ohne, dass ein Include verändert wurde.




Schau dir in der IDE Ausgabe, das log an, dann siehst du welche *.cpp 
und sonstige kompiliert werden.
1 bis 2 Dutzend *.o werden erzeugt.
Diese dann fein nacheinander in ein Archiv core.a gestopft.
Zu guter Letzt, bekommt der Linker anwendung.o und core.a vorgeworfen 
und macht seinen Job, incl. diverser Optimierungen, wie z.B. unbenutzte 
Methoden/Funktion/Variablen zu entsorgen.

Das aus der *.elf dann noch eine *.hex und eine *.eep gebastelt wird, 
geschenkt.


----
Die Arduino Besonderheit:
Machst du in der anwendung.ino ein #include <Irgendwas.h>
Dann findet der Arduino Builder das, durchsucht die Lib Ordner nach dem 
Kram, kopiert alle zugehörigen Dateien mit in den temporären build 
Ordner, und bezieht die dort gefundenen Übersetzungseinheiten mit ein.

Hier hat das Auskommentieren einer Lib eine etwas größere Tragweite.
Da eben der Builder selber Präprozessor spielt.

Wie gesagt: Eine Besonderheit.
Andere IDEs tun das nicht so, die halten sich an ihr Projekt Konzept.
Sind so evtl. etwas fixer.

von Veit D. (devil-elec)


Lesenswert?

Hallo Arduino Fanboy,

diese Erklärung kann ich nun nicht mehr falsch verstehen. Der Schuss hat 
gesessen. Hatte zwischendurch schon an mir gezweifelt. Auch schön das du 
mir die Antwort auf den Arduino libraries Ordner vorweg genommen hast. 
Darauf wäre ich auch noch gekommen, hat sich damit erledigt. Ich werde 
mir die Logausgabe genauer anschauen.
Vielen Dank für die Zeit und Mühe.
Damit kann ich dir abschließend deine Frage beantworten.  :-)
> Wie würdest du das denn lösen?
In C mit define Orgien und in C++ mit namespace.  :-)

Natürlich auch allen anderen vielen Dank, die ich nun auch verstehe. 
Manchmal braucht es bestimmte Worte.

Edit:
wünsche noch ruhige Ostern

: Bearbeitet durch User
von Veit D. (devil-elec)


Lesenswert?

Hallo,

eine Idee daraus folgend habe ich noch. Wenn der TO seine Libs auf 
Header only umschreibt, dann sollte er um define drumherumkommen und mit 
include<...> auskommen. Ich hoffe der TO liest noch mit.

von Einer K. (Gast)


Lesenswert?

Naja, dadurch, dass man alle Funktionen und Variablen in einer solche 
*.h als inline und/oder static definieren muss, könnte es schon 
unangenehme Seiteneffekte haben.
z.B. können die gelinkten Übersetzungseinheiten keine Daten mehr über 
Variablen austauschen, da jede Übersetzungseinheit ihren eigenen Satz an 
Funktionen/Variablen hat.
Auch könnte/wird der Programmspeicher und RAM Bedarf steigen.

Result:
Möglich!
Kann allerdings einen Rattenschwanz an Problemen mit sich bringen.

von Veit D. (devil-elec)


Lesenswert?

Hallo,

wenn nicht gut ist auch okay.

von A. S. (Gast)


Lesenswert?

Veit D. schrieb:
> ine Idee daraus folgend habe ich noch. Wenn der TO seine Libs auf
> Header only umschreibt, dann sollte er um define drumherumkommen und mit
> include<...> auskommen. Ich hoffe der TO liest noch mit.

Code in .h-Dateien und dann per include einbinden? Das ist das Gegenteil 
von strukturiert und modularisiert. Im Einzelfall gerechtfertigt, 
gegenüber den gängigen (und genannten) Alternativen Murks.

von Tuck I. (tuckito)


Lesenswert?

Ich lese noch mit. Ist schön was von der Blickwinkelkanone abzubekommen 
:-)

von MaWin (Gast)


Lesenswert?

A. S. schrieb:
> B) ... Er bindet dann
> jeweils das ganze Objectfile ein, also alles, was im zugehörigen C-File
> stand.

Bist du dir da sicher? ;->

von Einer K. (Gast)


Lesenswert?

ja

von A. S. (Gast)


Lesenswert?

MaWin schrieb:
> Bist du dir da sicher? ;->

Ja. Auch wenn heutige Compiler das unterdrücken können, weil sie es vom 
C++Bruder kennen.

von MaWin (Gast)


Lesenswert?

A. S. schrieb:
> Auch wenn heutige Compiler das unterdrücken

Das dürfte der Realität entsprechen. :-)

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.