Forum: Compiler & IDEs compilerfehler: multiple definition of `fuerporta'


von Paul S. (paulszymanski)


Lesenswert?

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_t muster0=0b111111111;
18
uint16_t muster1=0b111111111;
19
uint16_t muster2=0b111111111;
20
21
22
// 5V Spannungen auf Säulen legen (Anodenpins bei LEDs)
23
void multiplexSetColumns0(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
void multiplexSetColumns1(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
void multiplexSetColumns2(void) {
40
  PORTC = (muster2>>1);
41
  fuerporta = muster2 & ~0b111111110;
42
  fuerporta = (fuerporta<<multiplexLastColumn);
43
  PORTA = (fuerporta | PORTA);
44
}
45
46
void multiplexSetLevel(int freischaltung, int level) {
47
  if (freischaltung == 1) {
48
    portoff(etagenport,level);
49
  } else if (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
int main(void) {
19
  DDRC = 0xff; // C Pins als Ausgang setzen
20
  DDRA = 0xff; // A Pins als Ausgang setzen
21
  int ntesmuster = 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
    int time_ms = 1000;    // Zeit fü ein Muster
30
    const int delay = 1;      // Zeit für ein Frame in ms
31
    int loops = 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)
50
      
51
      loops--;
52
    }
53
    ++ntesmuster;
54
  }
55
56
return 0;
57
}
58
59
void portoff(char x, int n) {
60
  switch (x) {
61
    case 'A':
62
      PORTA &= ~(1<<n); break;
63
    case 'B':
64
      PORTB &= ~(1<<n); break;
65
    case 'C':
66
      PORTC &= ~(1<<n); break;
67
    case 'D':
68
      PORTD &= ~(1<<n); break;
69
      break;
70
  }    
71
}
72
73
void porton(char x, int n) {
74
  switch (x) {
75
    case 'A':
76
      PORTA |= (1<<n); break;
77
    case 'B':
78
      PORTB |= (1<<n); break;
79
    case 'C':
80
      PORTC |= (1<<n); break;
81
    case 'D':
82
      PORTD |= (1<<n); break;
83
      break;
84
  }    
85
}

multiplex.h
1
/*
2
 *  multiplex.h
3
 *  multiplex
4
 *
5
 *  Created by Paul Szymanski on 18.01.11.
6
 *
7
 */
8
9
#ifndef MULTIPLEX_H
10
#define MULTIPLEX_H
11
12
#include <avr/io.h>
13
14
#define etagenport 'A'
15
#define multiplexLastColumn 3
16
17
uint8_t fuerporta;  // Arbeitsvariable
18
19
#endif

von ich (Gast)


Lesenswert?

wenn du fuerporta in multiplex.h definierst und dann multiplex.h zwei 
mal wo einbindest hat du natürlich eine multiple definition...

von sven (Gast)


Lesenswert?

Ich denke DU musst inmultiplex.cpp deine Variable aus main.cpp bekannt 
machen ("extern" oder so)

von Paul S. (paulszymanski)


Lesenswert?

aus disem grund habe ich ja
#ifndef MULTIPLEX_H
#define MULTIPLEX_H
am anfang. der präprozessor sollte ein zweites einbinden somit doch 
verhindern?

von sven (Gast)


Lesenswert?

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

"

von Paul S. (paulszymanski)


Lesenswert?

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 :(

von Philipp (Gast)


Lesenswert?

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.

von Huch (Gast)


Lesenswert?

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

von Paul S. (paulszymanski)


Lesenswert?

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

von Philipp (Gast)


Lesenswert?

wenn du extern davor setzt, definierst du keine neue Variable, sondern 
sagst dem compiler das die variable irgendwo anders definiert ist.

von (prx) A. K. (prx)


Lesenswert?

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;

von Mark B. (markbrandis)


Lesenswert?

Philipp schrieb:
> Man sollte unter keinen umständen Variablen in headern definieren.

Warum nicht? Vorausgesetzt natürlich ich will eine globale Variable 
haben.

von Paul S. (paulszymanski)


Lesenswert?

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

von Paul S. (paulszymanski)


Lesenswert?

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?

von (prx) A. K. (prx)


Lesenswert?

Wie wärs mit einem C Buch?

von Paul S. (paulszymanski)


Lesenswert?

Ja wird angeschafft...

von Karl H. (kbuchegg)


Lesenswert?


von Philipp (Gast)


Lesenswert?

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.

von Philipp (Gast)


Lesenswert?

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

von Paul S. (paulszymanski)


Lesenswert?

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

von Philipp (Gast)


Lesenswert?

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.

von Karl H. (kbuchegg)


Lesenswert?

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.

von Paul S. (paulszymanski)


Lesenswert?

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 :)

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.