Hallo Community!
Ich frage mich gerade, ob es möglich ist, in einzelnen C-Modulen (also
Header-File + C-File) Funktionen mit gleichem Namen zu deklarieren und
zu definieren. Also beispielsweise habe ich eine Funktion
1
voidfunc(void);
die einmal in Modul 1 implementiert ist und auf eine andere Weise in
Modul 2.
In der Datei mit der main-Funktion inkludiere ich dann entweder Modul1.h
oder Modul2.h, je nachdem, welche func()-Implementierung ich jetzt
gerade verwenden will.
1
//#include "Modul1.h"
2
#include"Modul2.h"
3
4
intmain(void)
5
{
6
func();
7
//...
8
}
Das Ganze wird so wahrscheinlich nicht funktionieren, weil der Compiler
dann wegen mehrfacher Funktionsdefinitionen meckern wird, oder
(vorausgesetzt, dass beide Module kompiliert werden sollen)? Wie kann
man sowas geschickt lösen? Ist das mit C überhaupt lösbar? ;)
Danke!
Andi K. schrieb:> Wie kann> man sowas geschickt lösen? Ist das mit C überhaupt lösbar? ;)
einfach mit makros arbeiten und die Namen eindeutig machen.
Modul1
extern modul1_func( )
define func modul1_func
Modul2
extern modul2_func( )
define func modul2_func
Wenn du die Möglichkeit hast, mit einem C++ Compiler zu übersetzen, dann
kannst du Namespaces verwenden.
Über Umwege ist es dennoch in C möglich, und zwar indem du eine Struktur
mit Funktionspointern initialisierst, siehe 2. Antwort hier:
http://stackoverflow.com/questions/389827/namespaces-in-c
Edit: Sehe gerade, dass meine Antwort ein wenig am Problem vorbei geht.
Andi K. schrieb:> Ich frage mich gerade, ob es möglich ist, in einzelnen C-Modulen (also> Header-File + C-File) Funktionen mit gleichem Namen zu deklarieren und> zu definieren.
Nicht, wenn beide Module gleichzeitig ins Projekt gelinkt werden.
Dann bekommst Du einen Namenskonflikt.
Du kannst aber Umwege über Defines, Funktionspointer, bedingte
Kompilierung etc. machen.
Andi K. schrieb:> Ich frage mich gerade, ob es möglich ist, in einzelnen C-Modulen (also> Header-File + C-File) Funktionen mit gleichem Namen zu deklarieren und> zu definieren.
Nein, da es von der Sprache her überhaupt keine Module gibt. Die
Aufteilung in .h/.c ist eine reine Programmierkonvention. Es geht
allerdings innerhalb eines C Files, per "static".
Andi K. schrieb:> Hallo Community!>> Ich frage mich gerade, ob es möglich ist, in einzelnen C-Modulen (also> Header-File + C-File) Funktionen mit gleichem Namen zu deklarieren und> zu definieren.
Es kommt immer auf den Scope, also den Gültigkeitsbereich einer Funktion
(einer Variablen, einer Datenstruktur) an.
In C kann man eine Funktion als static deklarieren. Dann kann diese
Funktion nur innerhalb der gleichen Übersetzungseinheit aufgerufen
werden. Im Prinzip kann dann eine Funktion mit dem gleichen Namen in
jeder Übersetzungseinheit einmal enthalten sein. Ob es sinnvoll ist das
so zu machen, steht auf einem anderen Blatt. Wahrscheinlich eher nicht.
Funktionen (und Variablen, Datenstrukturen) mit dem gleichen Namen sind
innerhalb des gleichen Gültigkeitsbereichs nicht möglich. Wie sollte der
Compiler/Linker diese auch auflösen?
A. K. schrieb:> Die übliche Frage: Um was geht es wirklich? Also wofür wäre das von dir> ausgedachte Instrument die Lösung?
Man kann es nicht oft genug wiederholen:
Beschreibe nicht den Lösungsansatz, sondern beschreibe das zu lösende
Problem.
Der gewählte Lösungsansatz ist nämlich nicht selten völlig Banane. ;-)
> ... Also beispielsweise habe ich eine Funktion> void func(void);> die einmal in Modul 1 implementiert ist und auf> eine andere Weise in Modul 2.
Wenn es hingegen nur darum geht, verschiedene Implementierungen zu
vergleichen, dann wählt man normalerweise den einfachsten Weg, in dem
man mittels bedingter Compilierung eines der beiden Module mehr oder
weniger einfach 'aus dem Rennen nimmt'. Die entsprechenden Funktionen
werden dann gar nicht mitcompiliert, wodurch sich das Problem beim
Linken dann gar nicht mehr stellt.
Man kann natürlich auch im Makefile die entsprechende Unterscheidung
machen, welches der beiden Object-Files mitgelinkt werden soll, wenn die
Funtionsschnittstellen identisch sind. In einer IDE läuft das zb oft
darauf hinaus, dass man dann eigene 'Configurations' für jede Variante
hat. Wenn es aber zuviele austauschbare Teile gibt, ist die Variante mit
bedingter Compilierung meistens einfacher.
Es kommt eben immer drauf an, was die Absicht ist, wozu man das braucht
und wie allgemein und dauerhaft es sein soll.
Andi K. schrieb:> Ich frage mich gerade, ob es möglich ist, in einzelnen C-Modulen (also> Header-File + C-File) Funktionen mit gleichem Namen zu deklarierenKarl Heinz schrieb:> Es kommt eben immer drauf an, was die Absicht ist,...
Erstmal NEIN, es geht nicht und zweitens kann ich die Absicht durchaus
verstehen. Dem TO geht es einfach darum, eine gewisse Kapselung
herbeizuführen. Also, daß die Namen von lokalen Funktionen innerhalb
einer Quelle nicht kreuz und quer über das gesamte Projekt
"breitgetreten" werden. Man kann mit "static" arbeiten, aber das
empfinde ich als ein völlig hirnrissiges Wort für den gedachten Zweck.
Besser wäre "local" oder so ähnlich. Die Verwendung innerhalb von
Funktionen finde ich auch blöd, weil dadurch alle Otto
Normalprogrammierer zur Gedankenlosigkeit bei globalen Variablen
verleitet werden.
Typische Funktionen dieser Art sind "void delay(int usec);" und
Konsorten. Ob das nun von jedermann als guter Programmierstil erachtet
wird, ist Ansichtssache. Ich benutze sowas gelegentlich auch mal.
Tja, hier sind wir mal wieder an einem Geburtsfehler von C angelangt.
Bei Pascal wäre sowas nie passiert, da geht es schon immer viel
geordneter zu. Also bleibt dem TO nur eines übrig: persönliche
Schreib-Disziplin.
W.S.
Das Problem ist lösbar.
Jedes Modul enthält seine Implementierung von "func()", nennt diese aber
nicht einfach func, sondern verwendet einen eineindeutigen Namen, wie
z.B. die Kombination aus Modul- und Funktionsnamen.
Das hat "peter II" in seinem Beitrag -- der ersten Antwort im Thread
überhaupt -- auch schon knapp beschrieben.
Hier mal ein etwas erweitertes Beispiel:
modul1.c
Mit gcc kannst du Funktionen deklarieren, die überschrieben werden
können.
methodA() __attribute(weak);
Wird methodA nochmal woanders deklariert, so wird die "weak" deklarierte
verworfen.
W.S. schrieb:> Tja, hier sind wir mal wieder an einem Geburtsfehler von C angelangt.
Ja. Ist aber ein Fluch der frühen Geburt.
Die Idee formal definierter Module als Sprachbestandteil kam überhaupt
erst zu dem Zeitpunkt auf, zu dem C entstand. Aber erst in der zweiten
Hälfte der 70er setzte sich diese Idee allmählich durch. Lange nach der
Erfindung von C.
> Bei Pascal wäre sowas nie passiert, da geht es schon immer viel> geordneter zu.
In dieser Hinsicht war das Wirth'sche Pascal nicht besser. Wirth hatte
dieses Thema ebenso wenig auf dem Radar wie Ritchie. Weshalb er
Modula(-2) nachlegte. Pascal hatte also den gleichen Geburtsfehler -
aber noch nicht einmal Includes.
Andi K. schrieb:> Ich frage mich gerade, ob es möglich ist, in einzelnen C-Modulen (also> Header-File + C-File) Funktionen mit gleichem Namen zu deklarieren und> zu definieren. Also beispielsweise habe ich eine Funktion
1
>voidfunc(void);
> die einmal in Modul 1 implementiert ist und auf eine andere> Weise in> Modul 2.
Dein Ansatz ist genau falsch rum.
Du brauchst nur eine Header-Datei mit der Deklaration, aber 2 C-Dateien
mit den unterschiedlichen Implementierungen der Funktion, zB. "modul1.c"
und "modul2.c". Dein "main.c" wird einfach die einzige Header-Datei
inkludieren. Erst beim Linken entscheidest du ob modul1.c oder modul2.c
zu dein Programm gelinkt wird.
func.h:
> Erst beim Linken entscheidest du ob modul1.c oder> modul2.c zu dein Programm gelinkt wird.
Bei der einfachen Variante -- genau ein Funktionsaufruf aus main()
heraus -- ist das die sinnvollste Vorgehensweise.
Wenn aber die Funktionen beide zum Einsatz kommen sollen, nur an
anderen Stellen, dann ist die Makro-Variante zu nutzen.
Allerdings: Man könnte dann auch einfach hinschreiben, was man will, und
auf all diese Dinge verzichten.
Vielen Dank für eure Anregungen! :)
Sind ein paar sehr interessante Vorschläge dabei, die ich mir mal
genauer ansehen werde.
A. K. schrieb:> Die übliche Frage: Um was geht es wirklich? Also wofür wäre das von dir> ausgedachte Instrument die Lösung?
Die Fragestellung ist allgemein gehalten, weil ich hier keine konkrete
Anwendung habe, sondern nur ein paar Ideen sammeln wollte. Ich merke
aber an den Antworten, dass ich mich zu schwammig ausgedrückt habe.
Meine eigentliche Intention war es, entweder die eine Implementierung
der Funktion oder die andere auszuwählen und nie beide gleichzeitig
verwenden möchte. Und das ganze am besten so komfortabel wie möglich,
d.h. ohne bestimmte Dateien vom Kompilieren auszuschließen und ohne in
den darauf aufbauenden Dateien die Funktionen immer umbennen zu müssen,
je nachdem, ob gerade die eine oder andere Implementierungsart benutzt
werden soll.
Sehe ich richtig, dass das so mit Namespaces in C++ realisierbar ist?
Habe leider keine Erfahrung mit C++ ;)
Andi K. schrieb:> Meine eigentliche Intention war es, entweder die eine Implementierung> der Funktion oder die andere auszuwählen und nie beide gleichzeitig> verwenden möchte.
Das geht am einfachsten mit bedingter Kompilierung:
Andi K. schrieb:> Meine eigentliche Intention war es, entweder die eine Implementierung> der Funktion oder die andere auszuwählen und nie beide gleichzeitig> verwenden möchte. Und das ganze am besten so komfortabel wie möglich,> d.h. ohne bestimmte Dateien vom Kompilieren auszuschließen und ohne in> den darauf aufbauenden Dateien die Funktionen immer umbenennen zu müssen,> je nachdem, ob gerade die eine oder andere Implementierungsart benutzt> werden soll.
Willst du beide Varianten immer parallel erzeugen? (Wäre z.B. der Fall,
wenn du Code für zwei oder mehrere unterschiedliche Hardwarevarianten
erzeugen müsstest.) Dann würde ich ganz klar den Weg gehen, verschiedene
Objektdateien mit identischem Interface zu linken.
Wie kann das aussehen:
Dank eines kreativen Layouters hatte ich mal das Vergnügen, bei einem
Kartentelefon vier! nicht pin- und adresskompatible HW-Revisionen
bedienen zu müssen.
Alle Funktionen für diese "versionsabhängige Hardware" waren in einer
C-Datei zusammengefasst. Die Varianten wurden über passende Defines
unterschieden, dabei war das Interface zum Rest des Programms immer
gleich. Das Makefile enthielt entsprechend vier Targets (Objekt-Dateien)
mit entsprechender Build-Rule. Beim Linken wurde jeweils das passende
Objekt-File angegeben.
Andernfalls: Der alternative Weg über bedingte Übersetzung wurde ja
schon beschrieben.
Grüße
Stefan
man kann verschiedene Varianten einer Bibliothek auch in dlls bzw shared
libs packen und dann dynamisch aufrufen. Damit kann man sogar zur
Laufzeit entscheiden welche Variante benutzt wird.
Ist z.B. nützlich wenn ein Programm verschiedene Kommunikationskanäle
hat die nicht immer vorhanden sind.
z.B. unterschieliche Netzwerkimplementierungen, versch. Middelwares,
unterschiedliche Datenbanken etc.