Forum: Compiler & IDEs Modularisierung: Gleiche Funktionsnamen


von Andi K. (fry12)


Lesenswert?

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
void func(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
int main(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!

: Bearbeitet durch User
von Peter II (Gast)


Lesenswert?

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

von Alexander F. (alexf91)


Lesenswert?

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.

: Bearbeitet durch User
von Bronco (Gast)


Lesenswert?

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.

von (prx) A. K. (prx)


Lesenswert?

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".

von (prx) A. K. (prx)


Lesenswert?

Die übliche Frage: Um was geht es wirklich? Also wofür wäre das von dir 
ausgedachte Instrument die Lösung?

: Bearbeitet durch User
von Mark B. (markbrandis)


Lesenswert?

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. ;-)

: Bearbeitet durch User
von Mark B. (markbrandis)


Lesenswert?

Übrigens:
Wenn es darum geht, eine Art Polymorphismus in C abzubilden, dann nimmt 
man dafür Funktionszeiger.

Stackoverflow ist Dein Freund:
http://stackoverflow.com/questions/524033/how-can-i-simulate-oo-style-polymorphism-in-c

: Bearbeitet durch User
von Karl H. (kbuchegg)


Lesenswert?

> ... 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.

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


Lesenswert?

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

Karl 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.

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

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
1
void modul1_func()
2
{
3
  puts("modul1\n");
4
}

modul2.c
1
void modul2_func(void)
2
{
3
  puts("modul2\n");
4
}

modul1.h
1
void modul1_func(void);
2
#ifdef func
3
#error "func bereits definiert!"
4
#else
5
#define func modul1_func
6
#endif

modul2.h
1
void modul2_func(void);
2
#ifdef func
3
#error "func bereits definiert!"
4
#else
5
#define func modul2_func
6
#endif

main.c
1
#include "modul2.h"
2
3
int main(void)
4
{
5
  func();
6
}

von jisisi (Gast)


Lesenswert?

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.

von (prx) A. K. (prx)


Lesenswert?

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.

: Bearbeitet durch User
von outofthebox (Gast)


Lesenswert?

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
> void func(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:
1
int func(void);

main.c:
1
#include <stdio.h>
2
#include "func.h"
3
4
int main()
5
{
6
  printf("Func: %d\n", func());
7
}

modul1.c:
1
#include "func.h"
2
3
int func(void)
4
{
5
  return 1;
6
}

modul2.c:
1
#include "func.h"
2
3
int func(void)
4
{
5
  return 2;
6
}

Und dann liefert:
1
gcc -o test1 main.c modul1.c
2
gcc -o test2 main.c modul2.c
dir die 2 gewünschte Varianten.

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

> 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.

von Andi K. (fry12)


Lesenswert?

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++ ;)

von Bronco (Gast)


Lesenswert?

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:
1
#if BENUTZE_MODUL1
2
#define func func_modul1
3
#else
4
#define func func_modul2
5
#endif
6
...
7
x = func(a,b);

von Stefan W. (dl6dx)


Lesenswert?

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

von Udo S. (urschmitt)


Lesenswert?

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.

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.