www.mikrocontroller.net

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


Autor: Paul Szymanski (paulszymanski)
Datum:

Bewertung
0 lesenswert
nicht 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&f... 
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:
/*
 *  multiplex.cpp
 *  multiplex
 *
 *  Created by Paul Szymanski on 21.01.11.
 *
 */


#include "config.h"
#include "multiplex.h"
#include <avr/io.h>
#include "rncontrol1_4.h"



uint16_t muster0=0b111111111;
uint16_t muster1=0b111111111;
uint16_t muster2=0b111111111;


// 5V Spannungen auf Säulen legen (Anodenpins bei LEDs)
void multiplexSetColumns0(void) {
  PORTC = (muster0>>1);
  fuerporta = muster0 & ~0b111111110;
  fuerporta = (fuerporta<<multiplexLastColumn);
  PORTA = (fuerporta | PORTA);
}

// 5V Spannungen auf Säulen legen (Anodenpins bei LEDs)
void multiplexSetColumns1(void) {
  PORTC = (muster1>>1);
  fuerporta = muster1 & ~0b111111110;
  fuerporta = (fuerporta<<multiplexLastColumn);
  PORTA = (fuerporta | PORTA);
}

// 5V Spannungen auf Säulen legen (Anodenpins bei LEDs)
void multiplexSetColumns2(void) {
  PORTC = (muster2>>1);
  fuerporta = muster2 & ~0b111111110;
  fuerporta = (fuerporta<<multiplexLastColumn);
  PORTA = (fuerporta | PORTA);
}

void multiplexSetLevel(int freischaltung, int level) {
  if (freischaltung == 1) {
    portoff(etagenport,level);
  } else if (freischaltung == 0) {
    porton(etagenport,level);
  }
}

main.cpp:
/*
 *  main.cpp
 *  multiplex
 *
 *  Created by Paul Szymanski on 18.01.11.
 *
 */

#include <stdlib.h> 
#include <avr/io.h>
#include <util/delay.h>
#include "main.h"
#include "multiplex.h"
#include "config.h"
#include "rncontrol1_4.h"


int main(void) {
  DDRC = 0xff; // C Pins als Ausgang setzen
  DDRA = 0xff; // A Pins als Ausgang setzen
  int ntesmuster = 0;


  while(1) {
    porton('A', 0);    //Pullup an (Dadurch LEDs aus) Etage sperren
    porton('A', 1);    //Pullup an (Dadurch LEDs aus) Etage sperren
    porton('A', 2);    //Pullup an (Dadurch LEDs aus) Etage sperren
    
    int time_ms = 1000;    // Zeit fü ein Muster
    const int delay = 1;      // Zeit für ein Frame in ms
    int loops = time_ms/(3*delay);  // Berechnung für durchläufe des Loops für ein 'muster'
    
    
    while (loops != 0) {
      
      multiplexSetColumns0();      // 5V Spannungen auf Säulen legen (Anodenpins bei LEDs)
      multiplexSetLevel(1,0);      // Obere Etage freischalten (Kathodenpins auf Masse)
      _delay_ms(delay);        // delay ms warten
      multiplexSetLevel(0, 0);    // Obere Etage Sperren (Kathodenpins auf 5V)
      
      multiplexSetColumns1();      // 5V Spannungen auf Säulen legen (Anodenpins bei LEDs)
      multiplexSetLevel(1, 1);    // Mittlere Etage freischalten (Kathodenpins auf Masse)
      _delay_ms(delay);        // delay ms warten
      multiplexSetLevel(0, 1);    // Mittlere Etage Sperren (Kathodenpins auf 5V)
      
      multiplexSetColumns2();      // 5V Spannungen auf Säulen legen (Anodenpins bei LEDs)
      multiplexSetLevel(1, 2);    // Untere Etage freischalten (Kathodenpins auf Masse)
      _delay_ms(delay);        // delay ms warten
      multiplexSetLevel(0, 2);    // Untere Etage Sperren (Kathodenpins auf 5V)
      
      loops--;
    }
    ++ntesmuster;
  }

return 0;
}

void portoff(char x, int n) {
  switch (x) {
    case 'A':
      PORTA &= ~(1<<n); break;
    case 'B':
      PORTB &= ~(1<<n); break;
    case 'C':
      PORTC &= ~(1<<n); break;
    case 'D':
      PORTD &= ~(1<<n); break;
      break;
  }    
}

void porton(char x, int n) {
  switch (x) {
    case 'A':
      PORTA |= (1<<n); break;
    case 'B':
      PORTB |= (1<<n); break;
    case 'C':
      PORTC |= (1<<n); break;
    case 'D':
      PORTD |= (1<<n); break;
      break;
  }    
}



multiplex.h
/*
 *  multiplex.h
 *  multiplex
 *
 *  Created by Paul Szymanski on 18.01.11.
 *
 */

#ifndef MULTIPLEX_H
#define MULTIPLEX_H

#include <avr/io.h>

#define etagenport 'A'
#define multiplexLastColumn 3

uint8_t fuerporta;  // Arbeitsvariable

#endif

Autor: ich (Gast)
Datum:

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

Autor: sven (Gast)
Datum:

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

Autor: Paul Szymanski (paulszymanski)
Datum:

Bewertung
0 lesenswert
nicht 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?

Autor: sven (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

"

Autor: Paul Szymanski (paulszymanski)
Datum:

Bewertung
0 lesenswert
nicht 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 :(

Autor: Philipp (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Huch (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Paul Szymanski (paulszymanski)
Datum:

Bewertung
0 lesenswert
nicht 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"?

Autor: Philipp (Gast)
Datum:

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

Autor: A. K. (prx)
Datum:

Bewertung
0 lesenswert
nicht 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;

Autor: Mark Brandis (markbrandis)
Datum:

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

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

Autor: Paul Szymanski (paulszymanski)
Datum:

Bewertung
0 lesenswert
nicht 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...

Autor: Paul Szymanski (paulszymanski)
Datum:

Bewertung
0 lesenswert
nicht 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?

Autor: A. K. (prx)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Wie wärs mit einem C Buch?

Autor: Paul Szymanski (paulszymanski)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ja wird angeschafft...

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert

Autor: Philipp (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Philipp (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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();

Autor: Paul Szymanski (paulszymanski)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Philipp (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Paul Szymanski (paulszymanski)
Datum:

Bewertung
0 lesenswert
nicht 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 :)

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.