Hi,
beim kompilieren von folgendem code bekomme ich immer die Fehlermeldung:
multiple definition of `fuerporta'
Sorry das ich das forum damit belaste, aber ich sehe den fehler einfach
nicht. Da ich auch noch C anfänger bin, ist mir dieser fehler bestimmt
noch nicht mal bewusst...
Eine Dopellte definition finde ich einfach nicht. Alle meine
header-dateien enthalten #ifndef header_h #define header_h "CODE"
#endif.
Der Code hat ursprünglich funktioniert, bis ich ihn nach dem Tutorial
http://www.avrfreaks.net/index.php?name=PNphpBB2&file=viewtopic&t=48535&postdays=0&postorder=asc
aufgeräumt habe.
Ich hoffe es kann mir jemand helfen, sonst packe ich wieder alles in
eine main.cpp datei!
Die Ausgabe vom Compiler:
obj/multiplex.o: In function `multiplexSetColumns0()':
/Users/paul/Documents/Projects/multiplex/multiplex.cpp:24: multiple
definition of `fuerporta'
obj/main.o:/Users/paul/Documents/Projects/multiplex/main.cpp:60: first
defined here
multiplex.cpp:
1
/*
2
* multiplex.cpp
3
* multiplex
4
*
5
* Created by Paul Szymanski on 21.01.11.
6
*
7
*/
8
9
10
#include"config.h"
11
#include"multiplex.h"
12
#include<avr/io.h>
13
#include"rncontrol1_4.h"
14
15
16
17
uint16_tmuster0=0b111111111;
18
uint16_tmuster1=0b111111111;
19
uint16_tmuster2=0b111111111;
20
21
22
// 5V Spannungen auf Säulen legen (Anodenpins bei LEDs)
23
voidmultiplexSetColumns0(void){
24
PORTC=(muster0>>1);
25
fuerporta=muster0&~0b111111110;
26
fuerporta=(fuerporta<<multiplexLastColumn);
27
PORTA=(fuerporta|PORTA);
28
}
29
30
// 5V Spannungen auf Säulen legen (Anodenpins bei LEDs)
31
voidmultiplexSetColumns1(void){
32
PORTC=(muster1>>1);
33
fuerporta=muster1&~0b111111110;
34
fuerporta=(fuerporta<<multiplexLastColumn);
35
PORTA=(fuerporta|PORTA);
36
}
37
38
// 5V Spannungen auf Säulen legen (Anodenpins bei LEDs)
39
voidmultiplexSetColumns2(void){
40
PORTC=(muster2>>1);
41
fuerporta=muster2&~0b111111110;
42
fuerporta=(fuerporta<<multiplexLastColumn);
43
PORTA=(fuerporta|PORTA);
44
}
45
46
voidmultiplexSetLevel(intfreischaltung,intlevel){
47
if(freischaltung==1){
48
portoff(etagenport,level);
49
}elseif(freischaltung==0){
50
porton(etagenport,level);
51
}
52
}
main.cpp:
1
/*
2
* main.cpp
3
* multiplex
4
*
5
* Created by Paul Szymanski on 18.01.11.
6
*
7
*/
8
9
#include<stdlib.h>
10
#include<avr/io.h>
11
#include<util/delay.h>
12
#include"main.h"
13
#include"multiplex.h"
14
#include"config.h"
15
#include"rncontrol1_4.h"
16
17
18
intmain(void){
19
DDRC=0xff;// C Pins als Ausgang setzen
20
DDRA=0xff;// A Pins als Ausgang setzen
21
intntesmuster=0;
22
23
24
while(1){
25
porton('A',0);//Pullup an (Dadurch LEDs aus) Etage sperren
26
porton('A',1);//Pullup an (Dadurch LEDs aus) Etage sperren
27
porton('A',2);//Pullup an (Dadurch LEDs aus) Etage sperren
28
29
inttime_ms=1000;// Zeit fü ein Muster
30
constintdelay=1;// Zeit für ein Frame in ms
31
intloops=time_ms/(3*delay);// Berechnung für durchläufe des Loops für ein 'muster'
32
33
34
while(loops!=0){
35
36
multiplexSetColumns0();// 5V Spannungen auf Säulen legen (Anodenpins bei LEDs)
37
multiplexSetLevel(1,0);// Obere Etage freischalten (Kathodenpins auf Masse)
38
_delay_ms(delay);// delay ms warten
39
multiplexSetLevel(0,0);// Obere Etage Sperren (Kathodenpins auf 5V)
40
41
multiplexSetColumns1();// 5V Spannungen auf Säulen legen (Anodenpins bei LEDs)
42
multiplexSetLevel(1,1);// Mittlere Etage freischalten (Kathodenpins auf Masse)
43
_delay_ms(delay);// delay ms warten
44
multiplexSetLevel(0,1);// Mittlere Etage Sperren (Kathodenpins auf 5V)
45
46
multiplexSetColumns2();// 5V Spannungen auf Säulen legen (Anodenpins bei LEDs)
47
multiplexSetLevel(1,2);// Untere Etage freischalten (Kathodenpins auf Masse)
48
_delay_ms(delay);// delay ms warten
49
multiplexSetLevel(0,2);// Untere Etage Sperren (Kathodenpins auf 5V)
>>>wenn du fuerporta in multiplex.h definierst und dann multiplex.h zwei
mal wo einbindest hat du natürlich eine multiple definition...
Stimmt...von wegen
"Alle meine
header-dateien enthalten #ifndef header_h #define header_h "CODE"
#endif.
"
okay extern in multiplex.h war des rätsels lösung.
jetzt bekomme ich aber den fehler:
obj/multiplex.o: In function `multiplexSetColumns0()':
/Users/paul/Documents/Projects/multiplex/multiplex.cpp:26: undefined
reference to `fuerporta'
obj/multiplex.o: In function `multiplexSetColumns1()':
/Users/paul/Documents/Projects/multiplex/multiplex.cpp:34: undefined
reference to `fuerporta'
obj/multiplex.o: In function `multiplexSetColumns2()':
/Users/paul/Documents/Projects/multiplex/multiplex.cpp:42: undefined
reference to `fuerporta'
das sagt mir nun garnichts :(
Man sollte unter keinen umständen Variablen in headern definieren.
schreib sie in multiplex.cpp rein und in den header setzt du ein extern
davor dann wird es auch funktionieren.
>aus disem grund habe ich ja>#ifndef MULTIPLEX_H>#define MULTIPLEX_H>am anfang. der präprozessor sollte ein zweites einbinden somit doch>verhindern?
Wie Du nun festgestellt hast ist das eben nicht der Fall.
Der Preprozessor "merkt" sich nicht was er irgendwann mal beim
übersetzen einer anderen C-Datei an Definitionen gelesen hat. Er fängt
bei jeder C-Datei wieder von neuem an.
Philipp schrieb:> Man sollte unter keinen umständen Variablen in headern definieren.> schreib sie in multiplex.cpp rein und in den header setzt du ein extern> davor dann wird es auch funktionieren.
Danke es funktioniert :)
habe die definition jetzt komplett aus den header genommen. Was meintest
du mit "unter keinen umständen Variablen in headern definieren" und dann
aber "in den header setzt du ein extern davor"?
Paul Szymanski schrieb:> habe die definition jetzt komplett aus den header genommen. Was meintest> du mit "unter keinen umständen Variablen in headern definieren" und dann> aber "in den header setzt du ein extern davor"?
Definition != Deklaration.
// Definition, d.h. Platz wird reserviert. Nur einmal zulässig.
int x;
// Deklaration, es wird bekannt gemacht, dass es die irgendwo gibt.
extern int x;
Philipp schrieb:> Man sollte unter keinen umständen Variablen in headern definieren.
Warum nicht? Vorausgesetzt natürlich ich will eine globale Variable
haben.
ach so ist das! Danke! :)
und das deklarieren macht man aus dem grund, damit der compiler nicht
mekert "hey du hast die noch garnicht definiert" richtig?
darf ich eigendlich funktionen in header stecken? in meinem fall zum
beispiel porton() und portoff() aus main.cpp
diese funktionen brauche ich öfters...
Mark Brandis schrieb:> Philipp schrieb:>> Man sollte unter keinen umständen Variablen in headern definieren.>> Warum nicht? Vorausgesetzt natürlich ich will eine globale Variable> haben.
Ja wenn ich solche globale variable will, wie mache ich des denn?
einfach in i-einer c datei definieren, mit extern in das header-file und
mit #define globaleVariable 123 einfacher änderbar machen?
Mark Brandis schrieb:> Philipp schrieb:>> Man sollte unter keinen umständen Variablen in headern definieren.>> Warum nicht? Vorausgesetzt natürlich ich will eine globale Variable> haben.
weil header dateien für gewöhnlich ;) in vielen source dateien
eingebunden werden, was dann eben zu den fehler führt, um den es in
diesem theard geht.
will man eine globale variable in mehreren source dateien verwenden,
wird sie in einer source datei definiert und in allen anderen nur per
extern bekannt gemacht.
Paul Szymanski schrieb:> darf ich eigendlich funktionen in header stecken? in meinem fall zum> beispiel porton() und portoff() aus main.cpp> diese funktionen brauche ich öfters...
dafür schreibt man prototypen z.B.
int Funktion();
Ja das mit den prototypen ist mir bekannt aber ich muss ja trotzdem i-wo
die komplette funktion angeben... und jedes mal die funktion erst in
i-eine c-datei packen ist ja aufwändiger als einfach den header zu
includen
Paul Szymanski schrieb:> Ja das mit den prototypen ist mir bekannt aber ich muss ja trotzdem i-wo> die komplette funktion angeben... und jedes mal die funktion erst in> i-eine c-datei packen ist ja aufwändiger als einfach den header zu> includen
Du schreibst die Funktion genau ein einziges mal in ein Source Datei.
Den Prototypen schreibst du dann in eine Header Datei und bindest die in
jeder Source Datei ein, in der du die Funktion verwenden willst.
Paul Szymanski schrieb:> Ja das mit den prototypen ist mir bekannt aber ich muss ja trotzdem i-wo> die komplette funktion angeben... und jedes mal die funktion erst in> i-eine c-datei packen ist ja aufwändiger als einfach den header zu> includen
Du hast immer noch nicht verinnerlicht, dass ein komplettes Programm aus
mehrerer *.c Dateien besteht, die unabhängig voneinander compiliert und
die Ergebnisse des Compiliervorgangs dann zum kompletten Programm
zusammengelinkt werden.
Jede *.c wird für sich alleine compiliert. Besteht ein Projekt aus 2000
*.c Dateien, und gibt es eine Änderung in einer davon, dann wird auch
nur diese eine *.c neu compiliert und dann erneut das komplette Programm
daraus gelinkt.
Das ist das Um- und Auf, wie die Dinge in C funktionieren und warum
gewissen Dinge in C so sind, wie sie sind.
C an sich kennt abgesehen davon noch keinen Projektgedanken, wie er zb
in C# vorhanden ist. In C ist ein Projekt einfach nur eine Sammlung von
*.c Dateien, die noch nicht einmal alle auf dem gleichen Verzeichnis
sein müssen. C# lebt davon, dass es eine IDE gibt. Zu der Zeit, in der C
entstanden ist, wagte noch nicht einmal irgendjemand von einer IDE zu
träumen. Daher postuliert C auch nicht, dass es da etwas gibt, was ein
Projekt zusammenhält.
Besteht ein Projekt aus den Dateien main.c und helpers.c, dann wird
daraus ein ausführbares Progamm, indem auf einer Kommandline (also nix
Klikibunti)
cc helpers.c
cc main.c
die beiden Source Code Dateien einzeln compiliert werden. Aus helpers.c
wird ein helpers.o compiliert, welches schon Maschinencode enthält, aber
nur fpr die Teile die in helpers.c enthalten sind. Gleiches sinngemäss
für main.c
Die beiden Compilierergebnisse helpers.o und main.o werden dann mittels
link main.o helpers.o /output=program.exe
zum kompletten Programm program.exe zusammengebunden (+ natürlich noch
die notwendige Runtime Library, welche die vorgefertigten Funktionen
beisteuert).
So wird ein Programm in C gebaut. Und weil das so ist, weil helpers.c
extra compiliert wird, weil main.c extra compiliert wird, musste man
sich etwas einfallen lassen, dass zb die Sache mit Definitionen und
Deklarationen regelt.
Danke für die aufklärung!
Das Thema ist glaub ich soweit abgeschlossen.
Ich denke an das einzelne kompilieren und darauffolgendes linken und
besorg mir nun ein buch.
Danke für eure hilfe :)