www.mikrocontroller.net

Forum: Compiler & IDEs C-Syntax / Compiler


Autor: Gregor (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo!
Als Anfänger hab ich ein Problem mit dem gcc-compiler:
ich habe ein main.c mit

int main (void)
{
  funktion();
}

und eine Funktionen.c mit

void funktion (void)
{
 ; // tu was
}


Die Funktionen.c hab ich in WinAVR als SourceFile bekannt gemacht. Alles 
kompiliert auch schön. Aber woran liegt diese Zeile:

../Main.c:62: warning: implicit declaration of function `funktion'

Wo und wie kann ich die funktion() deklarieren?

Was kann ich unter WinAVR/gcc eigentlich schreiben? C, C++ oder beides?

Grüße, Gregor

Autor: Werner A. (homebrew)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Wenn Du die Sachen in eine Datei schreibst wird dir dass als Anfänger 
viel leichter fallen. Später kann man dann die Sachen in verschiedenen 
Dateien machen
Wenn Du das unbedingt trennen willst in main.c die funktion() als extern 
deklarieren, funktionen.c mit in das Makefile einbinden und anschließend 
die beiden Objektsfiles zusammen linken. oder so ungefähr.

Werner

Autor: Gregor (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Also so?

Main.c:

extern void funktion(void);
int main (void)
{
  funktion();
}

und

Funktionen.c:
void funktion (void)
{
 ; // tu was
}

So bekomme ich aber anstelle von Warnings nun jede Menge Errors.

Autor: Thomas (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Erstelle eine Header-Datei "Funktionen.h" in der du deine Funktionen 
Deklarierst.
Also in der .h
void funktion (void);
Wichtig ist dabei das Semikolon am Ende der Zeile.
In deiner Main.c schreibst du dann ganz am Anfang:
#include "Funktionen.h"
Dieses Include wird dann durch den Inhalt der Datei "Funktionen.h" 
ersetzt. Somit weiß der Compiler, wie deine Funktion "funktion()" 
aufzurufen ist.

Das ist die übliche Vorhegensweise, wie du sie auch in jedem 
Einsteiger-C-Buch finden wirst.

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

Bewertung
0 lesenswert
nicht lesenswert
Gregor wrote:
> Also so?
>
> Main.c:
>
> extern void funktion(void);
> int main (void)
> {
>   funktion();
> }
>
> und
>
> Funktionen.c:
> void funktion (void)
> {
>  ; // tu was
> }
>
> So bekomme ich aber anstelle von Warnings nun jede Menge Errors.

Und die wären?
Obiges ist 100% korrektes C.
In der Praxis macht man das zwar etwas anders (über eigene
Header Files) aber auch das läuft letztendlich genau auf
das was du da geschrieben hast hinaus.

Autor: Gregor (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Fehler wären:
warning: implicit declaration of function 'xyz'
error: conflicting types for 'xyz'
error: previous implicit declaration of 'xyz' was here
Build failed with 12 errors and 8 warnings...


Das komplette Projekt hab ich mal gezippt (2.5kB) und angehängt. Wäre 
nett wenn jemand nen kurzen Blick drüber wirft. Sollte auch gut zu lesen 
sein und ist nicht groß.
Kennt jemand ein Online-Tutorial oder -Kompendium für C ?  Für C++ gibts 
ja unmengen, aber für 'C' lässt es sich so schlecht googlen.


Autor: Gregor (Gast)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
hängt es jetzt dran?

Autor: WeiF (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi,

> Kennt jemand ein Online-Tutorial oder -Kompendium für C ?  Für C++ gibts
> ja unmengen, aber für 'C' lässt es sich so schlecht googlen.


schau mal auf

http://www.pronix.de/pronix-4.html

nach

Autor: Karl heinz Buchegger (kbucheg)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hier sind deine Fehlermeldungen:
../hw_control.c: In function `tempAusgeben':
../hw_control.c:109: warning: implicit declaration of function `lcd_gotoxy'
../hw_control.c:110: warning: implicit declaration of function `lcd_puts'
../hw_control.c: In function `LEDsSetzen':
../hw_control.c:162: warning: implicit declaration of function `LEDrt0'
../hw_control.c:163: warning: implicit declaration of function `LEDge0'
../hw_control.c:164: warning: implicit declaration of function `LEDgn1'
../hw_control.c:169: warning: implicit declaration of function `LEDge1'
../hw_control.c:170: warning: implicit declaration of function `LEDgn0'
../hw_control.c:174: warning: implicit declaration of function `LEDrt1'
../hw_control.c: At top level:
../hw_control.c:184: error: conflicting types for 'LEDgn1'
../hw_control.c:164: error: previous implicit declaration of 'LEDgn1' was here
../hw_control.c:189: error: conflicting types for 'LEDgn0'
../hw_control.c:170: error: previous implicit declaration of 'LEDgn0' was here
../hw_control.c:194: error: conflicting types for 'LEDrt1'
../hw_control.c:174: error: previous implicit declaration of 'LEDrt1' was here
../hw_control.c:199: error: conflicting types for 'LEDrt0'
../hw_control.c:162: error: previous implicit declaration of 'LEDrt0' was here
../hw_control.c:204: error: conflicting types for 'LEDge1'
../hw_control.c:169: error: previous implicit declaration of 'LEDge1' was here
../hw_control.c:209: error: conflicting types for 'LEDge0'
../hw_control.c:163: error: previous implicit declaration of 'LEDge0' was here

Jede Zeile beginnt mit
../hw_control.c

Das ist der Dateiname der Source Code Datei, in der der Fehler
aufgetreten ist. Du hast zwar 2 *.c Dateien in dein ZIP File
reingepackt, aber keines von beiden ist hw_control.c

Die ersten beiden Fehlermeldungen lauten:

../hw_control.c: In function `tempAusgeben':
../hw_control.c:109: warning: implicit declaration of function 
`lcd_gotoxy'

Aha. Der Fehler befindet sich also in der Funktion tempAusgeben()
Dort wird eine Funktion lcd_gotoxy() aufgerufen. Nur hat der Compiler
keinen Prototyp für lcd_gotoxy() gesehen. Also sagt er dir das.
Wahrscheinlich hast du einfach vergessen in hw_control() ebenfalls
einen #include "lcd.h" zu machen.

Was viele Neulinge nicht bedenken:
Jedes *.c File wird unabhängig von allen anderen *.c Files
übersetzt. Wenn du in main.c einen #include auf lcd.h machst,
dann ist das zwar nett, ist aber für hw_control.c völlig
uninteressant.
Das Konzept von C sieht vor, dass jedes einzelne *.c File,
dass zu einem Projekt gehört, unabhängig von allen anderen
übersetzt werden kann. Wenn du in einem Projekt 2000 *.c
Files hast und nur an einem eine Änderung machst, dann muss
daher auch nur dieses eine*.c File und nicht alle neu
übersetzt werden.


> Kennt jemand ein Online-Tutorial oder -Kompendium für C ?

Kauf dir ein Buch. Zu empfehlen ist
immer noch der Klassiker 'Kernighan & Ritchie'
Online Tutorials kommen selten über 20 Seiten hinaus und
sind oft fehlerhaft. Ein gutes Buch hat aber mindestens
150 Seiten. Irgendeinen Unterschied muss die unterschiedliche
Seitenzahl ja haben :-)

Autor: Detlef _a (detlef_a)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Hi,

angehängtes pdf finde ich als Einstieg und Ref. für C ganz ok. Hat 45 
Seiten, also mehr als 20 aber deutlich weniger als 150.

Cheers
Detlef

Autor: Gregor (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
hw_control.c = funktionen.c
lcd.h ist von fleury und wird in beiden files inkludiert

Wenn ich den deklarationsblock jeweils ohne 'extern' in die 
funktionen.c/hw_control.c kopiere, komiliert alles, aber trotzdem mit 
der Warnung, das vorher nicht deklariert wurde...

Build started 10.1.2007 at 12:55:00

../Main.c: In function `main':
../Main.c:55: warning: implicit declaration of function `wait_ms'
../Main.c:56: warning: implicit declaration of function `tempAusgeben'
../Main.c:57: warning: implicit declaration of function `keysAusgeben'
../Main.c:58: warning: implicit declaration of function `humAusgeben'
../Main.c:60: warning: implicit declaration of function `LEDsSetzen'

../hw_control.c: In function `tempAusgeben':
../hw_control.c:124: warning: implicit declaration of function 
`lcd_gotoxy'
../hw_control.c:125: warning: implicit declaration of function 
`lcd_puts'

Build succeeded with 7 Warnings...

Autor: Karl heinz Buchegger (kbucheg)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> hw_control.c = funktionen.c

Und das kann ich riechen.

> lcd.h ist von fleury und wird in beiden files inkludiert

Dann schau noch mal in Funktionen.c rein.
Da ist kein include drinn.

>
> ../Main.c: In function `main':
> ../Main.c:55: warning: implicit declaration of function `wait_ms'
> ../Main.c:56: warning: implicit declaration of function `tempAusgeben'
> ../Main.c:57: warning: implicit declaration of function `keysAusgeben'
> ../Main.c:58: warning: implicit declaration of function `humAusgeben'
> ../Main.c:60: warning: implicit declaration of function `LEDsSetzen'
>
> ../hw_control.c: In function `tempAusgeben':
> ../hw_control.c:124: warning: implicit declaration of function
> `lcd_gotoxy'
> ../hw_control.c:125: warning: implicit declaration of function
> `lcd_puts'
>
> Build succeeded with 7 Warnings...

Es geht immer noch um dasselbe.
Du rufst eine Funktion auf, bevor der Compiler einen Prototypen
dafür gesehen hat.

C ist ein One-Pass Compiler.
D.h. der Compiler geht den Source Code von oben nach unten durch.
Ein einziges mal. Nicht öfter!
Wenn du eine Funktion aufrufst, dann muss ein Prototyp vor
dem Aufruf der Funktion vorkommen. Dahinter reicht nicht.
Ebensowenig reicht es, wenn die aufgerufene Funktion im
selben Source Code File vorkommt, wie der Aufruf:

int main()
{
  foo();
}

void foo()
{
}

Der Compiler geht von oben nach unten durch. Wenn der Aufruf
von foo() angetroffen wird, wurde nach kein Protoyp für foo()
gesehen.
* Entweder man setzt einen Prototypen an den Anfang

  void foo( void );

  int main()
  {
    foo();
  }

  void foo()
  {
  }

* oder man zieht die Funktion vor die Stelle des Aufrufs

  void foo()
  {
  }

  int main()
  {
    foo();
  }

Beide Fälle laufen auf das gleiche hinaus: Bevor der Aufruf
der Funktion foo() angetroffen wird, wurde der Compiler schon
mit der Funktion foo() vertraut gemacht: Es gibt sie (könnte
ja auch ein Schreibfehler sein), sie hat keine Argumente und
sie liefert auch keinen Returnwert. Das reicht; mehr muss der
Compiler nicht wissen um überprüfen zu können, ob der Funktions-
aufruf auch wirklich rechtens ist.

PS: Das 'extern' bei Funktionsprotoypen kannst du dir sparen.

Autor: Gregor (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Problem gelöst:

Es muss zwei mal deklariert werden. Im
Main.c:
extern void funktion(void);
int main (void)
{
  funktion();
}

und

Funktionen.c:
<b>void funktion (void);</b>
void funktion (void)
{
 ; // tu was
}

da sonst funktion() noch nicht bekannt ist, falls im Funktionen.c vor 
der funktion() eine überfunktion() die funktion() aufruft. dann wird die 
funktion() nämlich tatsächlich implizit deklariert.

Gut, wenn man nochmal drüber nachdenkt. ;o)

Vielen Dank an alle, die mich zum Denken angeregt haben!

Autor: Karl heinz Buchegger (kbucheg)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> Es muss zwei mal deklariert werden. Im
> Main.c:
> extern void funktion(void);
> int main (void)
> {
>   funktion();
> }
>
> und
>
> Funktionen.c:
> <b>void funktion (void);</b>
> void funktion (void)
> {
>   ; // tu was
> }

Nachdem du jetzt eingesehen hast, warum das so sein muss:

Genau so macht man es dann in der Praxis nicht.
In der Praxis macht man:

Man macht eine Datei Funktionen.h

Funktionen.h
************

void funktion(void);


und includiert die dann
* auf jeden Fall in Funktionen.c
 in allen anderen .c, die eine Funktion aus Funktionen.c
  aufrufen möchten

Funktionen.c
************
#include ....
#include ....
#include "Funktionen.h"

void funktion()
{
  hier ist die Implementierung
}


Main.c
******
#include ...
#include ...
#include "Funktionen.h"     // ich möchte was aus Funktionen.c
                            // benutzen

int main()
{
  funktion();
}

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.