Forum: Compiler & IDEs wie C-Programm abschließen?


von Günther (Gast)


Lesenswert?

Hi

Mein Compiler (avr-gcc) neigt etwas zur Nörgelei.
Wenn ich am Ende einer Funktion (z.B. main() )
nach der letzten Anweisung ein Semikolon setze,
dann eine Leerzeile lasse und schließlich die schließende
geschweifte Klammer, also
      Anweisung ;

}  /* Ende main */


dann  quittiert er das mit der Fehlermeldung
parse error before  „}“  token.

Wenn ich es, ich weiß nicht wie, geschafft habe, dann kommt
wenigstens, aber diesmal nur als Warnung, der Hinweis:
Contol reaches end of non-void function

Wie muß denn ein Programm gcc-gerecht enden?
In meinen Büchern über C-Programmierung enden die
Beispiele so wie oben und irgendwelche speziellen Hinweise
habe ich trotz langen Suchens nirgends gefunden.
Kann mir jemand helfen?

Günther

von Divison (Gast)


Lesenswert?

Ist dein Quellcode vieleicht zu lang? ISt vieleicht viel weiter unten
noch ne Klammer?

Oder ist es ist ein Fehler weiter oben in dem Programm. Hatte auch
schon das Problem, das ich eine Klammer irgendwo im Quelltext nicht
richtig hatte, er aber unten gemeckert hat.

#include <stdlib.h>
int main(void)
{
   while (1){
   //Endlosschleife
   }
}

Da kommt bei mir das raus. Also keine Feheler

set -e; avr-gcc -MM -mmcu=at90s8535 -I. -g -Os -funsigned-char
-funsigned-bitfields -fpack-struct -fshort-enums -Wall
-Wstrict-prototypes -Wa,-adhlns=leer.lst  -std=gnu99 leer.c \
| sed 's,\(.*\)\.o[ :]*,\1.o \1.d : ,g' > leer.d; \
[ -s leer.d ] || rm -f leer.d

-------- begin --------
avr-gcc (GCC) 3.3.1
Copyright (C) 2003 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is
NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR
PURPOSE.


Compiling: leer.c
avr-gcc -c -mmcu=at90s8535 -I. -g -Os -funsigned-char
-funsigned-bitfields -fpack-struct -fshort-enums -Wall
-Wstrict-prototypes -Wa,-adhlns=leer.lst  -std=gnu99 leer.c -o leer.o

Linking: leer.elf
avr-gcc -mmcu=at90s8535 -I. -g -Os -funsigned-char -funsigned-bitfields
-fpack-struct -fshort-enums -Wall -Wstrict-prototypes
-Wa,-adhlns=leer.o  -std=gnu99 leer.o   --output leer.elf
-Wl,-Map=leer.map,--cref -lm

Creating load file for Flash: leer.hex
avr-objcopy -O ihex -R .eeprom leer.elf leer.hex

Creating load file for EEPROM: leer.eep
avr-objcopy -j .eeprom --set-section-flags=.eeprom="alloc,load" \
--change-section-lma .eeprom=0 -O ihex leer.elf leer.eep

Creating Extended Listing: leer.lss
avr-objdump -h -S leer.elf > leer.lss

Creating Symbol Table: leer.sym
avr-nm -n leer.elf > leer.sym

Size after:

    Flash     SRAM     EEPROM
    -----     ----     ------
       1%       0%         0%


Errors: none
-------- end --------

von Divison (Gast)


Angehängte Dateien:

Lesenswert?

Hier ist das mal mit meinem makefile.

Kannste ja mal ausprobieren.

von OldBug (Gast)


Lesenswert?

Also so ein quatsch!

int
main(void)

Muss natürlich IMMER mit einem return enden, da diese Funktion ja
schliesslich was zurückliefern soll!

int
main(void)
{
  bla...;
  while(1);

  /* NEVERREACHED */
  return 0;
}

Wenn die Funktion nichts liefern soll, dann MUSS man main als void
deklarieren:

void
main(void)
{
  bla...;
  while(1);
}

Dann gibts allerdings die Warnung: "return type of `main´ is not
`int´", die man dann ignorieren darf (oder man schaltet sie mit
-Wno-main aus).

Gruß,
Patrick...

von Jörg Wunsch (Gast)


Lesenswert?

GCC besteht übrigens nicht auf dem nicht erreichbaren return, d. h.

int
main(void)
{

  for (;;) {
    ..
  }
}

wird nicht angemeckert.

Das »void main()« sollte man sich besser gar nicht angewöhnen, es ist
vom Standard schlicht nicht vorgesehen.  Spätestens, wenn man mal C++
machen möchte, ist alles andere als

int main(void);

oder

int main(int, char **);

ein Fehler.

von Divison (Gast)


Lesenswert?

Es ging doch um das beenden der main funktion, und nicht was sie
zurückliefern soll.

@oldbug -->  Was erzählst du denn dann da? Recht haste ja, aber darum
ging es doch garnicht.

von OldBug (Gast)


Lesenswert?

@Divison
Natürlich ging es darum!
Das fehlende return ist doch Ursache dieser Fehlermeldung!
Nicht, daß das jetzt in den falschen Hals gerät, das ist absolut nicht
böse gemeint!

@Jörg
Das trifft aber nur auf avr-gcc zu, nicht wahr?

@allgemein
Der einzige Grund, warum void main(void) verwendet, war mir lange
schleierhaft. Irgendwann habe ich dann mal gelesen, daß man damit ein
Stackframe spart... Ob das Sinn macht, oder nicht, liegt dann demnach
wohl im Auge des Betrachters :-)

Gruß,
Patrick...

von OldBug (Gast)


Lesenswert?

P.S.: ...ums noch deutlicher zu machen: das return 0; beendet in
meinem Beispiel die Funktion main()
Eine Funktion als "nicht void" zu deklarieren und kein return
einbauen ist in meinen Augen einfach nur falsch...

Gruß,
Patrick...

von Divison (Gast)


Lesenswert?

Hmmm

das ist nicht ganz richtig was du da sagst. Ein return gibt immer nur
einen Wert zurück. Mehr nicht. Es beendet keine Schleifen oder
Bedingungen oder sonst irgendwas.

Das Ende der Mainfunktion ist schlichtweg die }.

Wenn die Funktion main kein return hat, dann gibt sie halt nix zurück.
Kann fehler machen beim errorhandling aber wen das nicht stört.

Meine int main oben hat auch kein return 0. Geht aber prima! Würde mich
auch arg wundern wenn nicht.

Ach ja ich hab das nicht in den falschen hals bekommen. Sind ja hier
alle gross genug um Kritik zu ertragen. Dafür sind wir ja auch mitunter
hier.

von OldBug (Gast)


Lesenswert?

Da würd ich mich aber jetzt mal nicht drauf verlassen, daß Deine
Funktionen ohne return NICHTS zurück geben!
Mach mal folgendes:

int
testfunktion(void)
{
  /* gar nichts machen! */
}

int
main(void)
{
  printf("%d\n", testfunktion());
}

Vielleicht erstaunt Dich das Ergebnis ja ;)

Gruß,
Patrick...

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.