Forum: Mikrocontroller und Digitale Elektronik int main (void) warum nicht char main (void)


von Stefanus kj (Gast)


Lesenswert?

Wieso nimmt man eigentlich immer int main(void) und nicht Typ char?
In der Regel geht es nur noch um einen Rückgabewert 0 oder 1 und selbst 
wenn man einen anderen Wert übergeben wollte, würde char doch 
ausreichen?

von Sebastian R. (sebastian_r569)


Lesenswert?

Weil es eben Fälle gibt, in denen ein Char nicht ausreicht. Du kannst 
halt frei definieren, was dein Programm zurück gibt.

Wenn dein Programm irgendwas zählt, dann kann das z.B. ein Zählwert 
sein, der größer als ein Char ist. Wobei größer als int dann natürlich 
auch nicht geht.

von Wegstaben V. (wegstabenverbuchsler)


Lesenswert?

Stefanus kj schrieb:
> und nicht Typ char?

Stefanus kj schrieb:
> würde char doch ausreichen?


möglicherweise weil "CHAR" zu unspezifisch ist? returncodes (zumindest 
innerhalb von SHELL scripten) sind typscherweise im Berich [0 .. 255]. 
Du bräuchtest also zumindest "unsigned char" (bei einem 8-bit 
Zeichensatz auf deinem Zielsystem)

Sebastian R. schrieb:
> Wenn dein Programm irgendwas zählt, dann kann das z.B. ein Zählwert
> sein, der größer als ein Char ist.


Ich denke nichtm das es eine gute Idee ist, einen Werte-Parameter (z.B. 
Zählwert) als Return-Code zurück zu geben.

: Bearbeitet durch User
von Thomas M. (Firma: https://img.favpng.com/23/21/3) (thomasmopunkt)


Lesenswert?

gut dann eben uchar...das meinte ich auch, also Werte von 0.254

von Niklas G. (erlkoenig) Benutzerseite


Lesenswert?

Weil der C-Standard das so vorschreibt:
http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1570.pdf S. 13:

The function called at program startup is named main. [...] It  shall 
be  defined with a return type  of int ...

von Wegstaben V. (wegstabenverbuchsler)


Lesenswert?

Thomas M. schrieb:
> also Werte von 0.254

0..255.
Alles was draüber hinaus geht wird "Modulo" abgehackt.

von Axel S. (a-za-z0-9)


Lesenswert?

Stefanus kj schrieb:
> Wieso nimmt man eigentlich immer int main(void) und nicht Typ char?

Weil es so im Standard steht.

> In der Regel geht es nur noch um einen Rückgabewert 0 oder 1 und selbst
> wenn man einen anderen Wert übergeben wollte, würde char doch
> ausreichen?

Nur in deiner begrenzten Weltsicht. Wenn man einen negativen Wert 
zurückgeben will (-1 ist gängig für "Fehler"), dann reicht char 
regelmäßig nicht aus, weil char je nach Plattform ganz legal unsigned 
sein kann. Bei int hingegen ist garantiert, daß es ein signed Typ ist.

Auf einem µC ist das sowieso alles akademisch, weil es nichts gibt, das 
den Rückgabewert von main() lesen und etwas damit anfangen könnte.

von Roth (Gast)


Lesenswert?

spannendes Thema

Es ist Montag, aber mache haben anscheinend schon WE

von Niklas G. (erlkoenig) Benutzerseite


Lesenswert?

Thomas M. schrieb:
> gut dann eben uchar

Was ist denn uchar? Einer der Typen char16_t oder char32_t welche in der 
<uchar.h> definiert werden?

Axel S. schrieb:
> Auf einem µC ist das sowieso alles akademisch, weil es nichts gibt, das
> den Rückgabewert von main() lesen und etwas damit anfangen könnte.
Der Startup-Code könnte das, ist aber unüblich. Da auch auf 
PC-Betriebssystemen die main() nur indirekt aufgerufen wird (z.B. von 
einer Funktion _start), wird der Return-Wert da auch noch einmal 
durchgereicht, z.B. an den exit-Syscall.

von Walter K. (vril1959)


Lesenswert?

Axel S. schrieb:
> dann reicht char
> regelmäßig nicht aus, weil char je nach Plattform ganz legal unsigned
> sein kann.
manchmal ist char unsigned - aber ganz sicher nicht regelmäßig, eher 
selten

von Thomas M. (Firma: https://img.favpng.com/23/21/3) (thomasmopunkt)


Lesenswert?

"Weil der C-Standard das so vorschreibt:"

Was ist denn das für eine Erklärung?! WEIL ES SO IST....
Sorry..aber das erklärt z.B,. nicht weshalb das als Standard genommen 
wurde..
Also dann für die für die es einfach der Standard ist...wieso?

von Thomas M. (Firma: https://img.favpng.com/23/21/3) (thomasmopunkt)


Lesenswert?

"Was ist denn uchar?"
rate mal was damit gemeint sein könnte..macht man umgangssprachlich, 
Worte abzukürzen...

von Hans-Georg L. (h-g-l)


Lesenswert?

Weil ein int die Größe eines MC Registers hat und der return Wert in 
einem Register an den Startup Code zurückgegeben wird. Du sparst mit 
einem Char überhaupt nichts.

von Michael B. (laberkopp)


Lesenswert?

Stefanus kj schrieb:
> Wieso nimmt man eigentlich immer int main(void) und nicht Typ char?
> In der Regel geht es nur noch um einen Rückgabewert 0 oder 1 und selbst
> wenn man einen anderen Wert übergeben wollte, würde char doch
> ausreichen?

Weil der Aufrufer erwartet, daß ein int, also 16 oder 32 bit, 
zurückkommen, und nicht nur 8 bit und der Rest uninitialisiert und damit 
zufällig ist.

von Philipp Klaus K. (pkk)


Lesenswert?

Axel S. schrieb:
> Stefanus kj schrieb:
>> Wieso nimmt man eigentlich immer int main(void) und nicht Typ char?
>
> Weil es so im Standard steht.
>

Und dass es so im Standard steht, deutet darauf hin, dass es durchaus 
Anwendungen gab, bei denen char oder unsigned char nicht gereicht hätte 
(z.B. OpenVMS, dass tatsächlich den ganzen 32 Bit, die ein int auf 
diesem System hat, Bedeutung im Rückgabewert gibt). Auch wenn bei den 
heute üblichen POSIX-Systemen ein unsigned char ausreichend wäre.

> […]
>
> Auf einem µC ist das sowieso alles akademisch, weil es nichts gibt, das
> den Rückgabewert von main() lesen und etwas damit anfangen könnte.

Auf µC ist die C-Implementierung ja üblicherweise freestanding, womit 
Name und Typ der Startfunktion Implementierungsabhänging sind. Bei SDCC 
wird üblicherweise void main(void) verwendet, auch wenn SDCC auch mit 
ein paar anderen Varianten zurechtkommt.

Philipp

von Luther B. (luther-blissett)


Lesenswert?

Der Standard schreibt es so vor, weil es systemspezifisch ist, welche 
Rückgabewerte vom Host verarbeitet werden können. Während unter den 
meisten Unixen der Rückgabewert auf den Bereich 0-255 beschnitten wird, 
kann Windows z.B. den vollen Bereich von int als Rückgabewert verwenden 
und definiert auch eine ziemlich umfangreiche Liste von Error codes:

https://docs.microsoft.com/en-us/windows/desktop/debug/system-error-codes

von Niklas G. (erlkoenig) Benutzerseite


Lesenswert?

Thomas M. schrieb:
> Was ist denn das für eine Erklärung?! WEIL ES SO IST....

"Warum macht man das so" ist eine andere Frage als "Warum steht das im 
Standard so". In C macht man eine ganze Reihe von Dingen, weil sie vom 
Standard so vorgeschrieben sind, deren Sinn auch eher fragwürdig ist. 
Zwecks Kompatibilität zu bestehenden Systemen muss man das halt so 
machen.

Thomas M. schrieb:
> Also dann für die für die es einfach der Standard ist...wieso?
Vermutlich weil "int" historisch einem Prozessor-Register entsprach und 
deshalb am Effizientesten übergeben werden kann; daher wird es in C und 
insbesondere dem POSIX-API ja auch für alle möglichen Werte benutzt. Das 
stimmt dann z.B. bei AVR oder AMD64 aber nicht mehr.

Thomas M. schrieb:
> rate mal was damit gemeint sein könnte..macht man umgangssprachlich,
> Worte abzukürzen...
C ist aber keine Umgangssprache. Man sollte schon präzise ausdrücken was 
man meint. Ich hätte von "uchar" jetzt auf <uchar.h> gefolgert.

von Yalu X. (yalu) (Moderator)


Lesenswert?

Andersherum gefragt: Warum sollte man für einen ganzzahligen
Rückgabewert etwas anderes als den gewöhnlichsten aller Ganzzahltypen,
nämlich int nehmen?

Minimale Vorteile hätte char oder unsigned char allenfalls bei
8-Bit-Prozessoren, aber die waren nicht die Zielarchitektur bei der
Entwicklung von C.

von Thomas M. (Firma: https://img.favpng.com/23/21/3) (thomasmopunkt)


Lesenswert?

Danke, das erste mal seit langem wieder brauchbare Antworten in diesem 
Forum und kaum Ausreißer.

Na eben wenn es aber um AVR geht, würde ja char reichen, klar geht es 
nicht un ein Byte hier oder dort..aber als Anfänger macht es wohl Sinn 
sowas zu hinterfragen und nicht einfach möglichen fehlerhaften 
Lehrmeinungen nachzulaufen


Durch sowas werden einmal falsch in die Welt gesetzte Meinungen sonst 
immer wieder fortgetragen, eben weil jemand es EINFACH SO MACHT...das 
finde ich immer sehr fragwürdig...

: Bearbeitet durch User
von Lesbarkeiter (Gast)


Lesenswert?

1
#define uchar unchar char
2
#define unchar unsigned
3
#define unchar_uchar uchar // wegen der besseren Lesbarkeit
4
#define unchar_main unchar main
5
unchar_main() {
6
}

Man sollte aber auch an die Watbarkeit denken und und den abweichenden 
Typ von main() klar+deultich kennbar anmachen

von Lesbarkeiter (Gast)


Lesenswert?

Sorry kleiner Fehler,
 so ist es richtig
1
#define uchar unchar char
2
#define unchar unsigned
3
#define unchar_uchar uchar // wegen der besseren Lesbarkeit
4
#define unchar_main unchar_uchar main
5
unchar_main() {
6
}

von Michael B. (laberkopp)


Lesenswert?

Thomas M. schrieb:
> Na eben wenn es aber um AVR geht, würde ja char reichen,

?!?

Auf einem AVR gibt es überhaupt niemanden, der sich für den Rückgabewert 
interessiert.

Da kannst du void oder char hinschreiben, wenn du returnst, dann ist 
sowieso alles im Arsch.

von Thomas M. (Firma: https://img.favpng.com/23/21/3) (thomasmopunkt)


Lesenswert?

ach herje..hör doch mal mit dem uchar auf..das war doch nur eine 
Abkürzung da ich auf dem Handy im Forum geschrieben hatte ;-)

von Thomas M. (Firma: https://img.favpng.com/23/21/3) (thomasmopunkt)


Lesenswert?

ja, aber auch darüber regen sich ja wieder andere auf wenn man void 
main(void) schreibt..
+Irgendwie regen sich bei C eigentlich alle immer über alles auf weil 
irgendwie immer alles falsch oder nicht so richtig richtig 
ist....jaja...schreibt ein Pascal/Delphi Anwender ;-)

Wir brauchen jetzt aber keine C/Deplphi Diskussion darauf wollte ich 
nicht hianus, tief im innern wissen sowieso alle das Pascal besser ist 
hehe ;-)

von Niklas G. (erlkoenig) Benutzerseite


Lesenswert?

Thomas M. schrieb:
> Durch sowas werden einmal falsch in die Welt gesetzte Meinungen sonst
> immer wieder fortgetragen, eben weil jemand es EINFACH SO MACHT...das
> finde ich immer sehr fragwürdig...

Man programmiert aber nicht nach "Meinung". Man programmiert danach, was 
zum System passt. Und wenn man C programmiert, arbeitet man nach dem 
C-Standard; die Compiler erwarten C-Standard-konformen Code von dir. Du 
kannst zwar auch deine eigene Meinung eingeben, aber das wird dann nicht 
immer so gut funktionieren.

Die Überleitung von C-Programmieren zu Nazivergleichen ist... gekonnt.

Lesbarkeiter schrieb:
> #define unchar unsigned
Hurra, endlich ist "unchar int" gültige Syntax und kein Compiler-Fehler 
mehr! Benutz doch wenigstens typedef ...

von Dussel (Gast)


Lesenswert?

Thomas M. schrieb:
> ja, aber auch darüber regen sich ja wieder andere auf wenn man void
> main(void) schreibt..
Weil es einfach absolut keinen Grund dafür gibt. "int main" kostet 
praktisch nicht oder sogar absolut nichts. Dafür verstößt "void main" 
nicht nur gegen die Konvention, sondern ist ungültiges C.
Mir fallen drei Gründe für "void main" ein.
1. Es handelt sich nicht um C.
2. Der Programmierer lehnt sich in pubertärem Trotz gegen diese dummen
    anderen Programmierer auf.
3. Der Programmierer weiß es nicht besser.

von Markus F. (mfro)


Lesenswert?

Walter K. schrieb:
> Axel S. schrieb:
>> dann reicht char
>> regelmäßig nicht aus, weil char je nach Plattform ganz legal unsigned
>> sein kann.
> manchmal ist char unsigned - aber ganz sicher nicht regelmäßig, eher
> selten

Nun, auf Plattformen, bei denen char unsigned ist, ist char immer 
unsigned. Und immer ist meiner Meinung nach ziemlich oft...

Axel S. schrieb:
> Wenn man einen negativen Wert
> zurückgeben will (-1 ist gängig für "Fehler"), dann reicht char
> regelmäßig nicht aus, weil char je nach Plattform ganz legal unsigned
> sein kann. Bei int hingegen ist garantiert, daß es ein signed Typ ist.

... und das dürfte tatsächlich der wahre Grund sein: main() wäre nicht 
mehr portabel. Je nachdem, ob char auf der gewählten Plattform signed 
oder unsigned wäre, würde main mal positive oder mal negative 
Returnwerte ausspucken. Und das wäre ziemlich eklig.

Andererseits ist ein int definiert mit der "natürlichen Größe" für einen 
Datentyp einer bestimmten Architektur.

Was wäre natürlicher, als den Datentyp mit natürlicher Größe als 
Rückggabewert für main() zu verwenden?

von Markus F. (mfro)


Lesenswert?

Dussel schrieb:
> Dafür verstößt "void main"
> nicht nur gegen die Konvention, sondern ist ungültiges C.

Nein.

Im Gegensatz zum "hosted environment" ist für ein "freestanding 
environment" (das ist das, worüber man auf einer µC-Seite üblicherweise 
redet) Name und Typ der Funktion, die beim Programmstart gerufen wird 
"implementation defined". Da darf es ein void main(void) also durchaus 
geben.

von Yalu X. (yalu) (Moderator)


Lesenswert?

Thomas M. schrieb:
> Na eben wenn es aber um AVR geht,

... must du dir keine Sorgen machen:

Die allermeisten AVR-Programm laufen sowieso in einer Endlosschleife.
Der AVR-GCC (getestet mit 8.2.0) erkennt dies und lässt dann die
Instruktionen für den Rückgabe des Funktionswerts weg, auch wenn main
als int deklariert ist.

von Dussel (Gast)


Lesenswert?

Markus F. schrieb:
> Dussel schrieb:
>> Dafür verstößt "void main"
>> nicht nur gegen die Konvention, sondern ist ungültiges C.
>
> Nein.
>
> Im Gegensatz zum "hosted environment" ist für ein "freestanding
> environment" (das ist das, worüber man auf einer µC-Seite üblicherweise
> redet) Name und Typ der Funktion, die beim Programmstart gerufen wird
> "implementation defined". Da darf es ein void main(void) also durchaus
> geben.
Meine Antwort bezieht sich natürlich nur auf Anwendungsprogramme und 
wurde sowieso total falsch verstanden. ;-)

Nein, leider muss ich zugeben, dass ich falsch lag. :-( Danke für die 
Richtigstellung.

von Dussel (Gast)


Lesenswert?

Aber mit dem Fehler stehe ich nicht alleine da.
http://www.stroustrup.com/bs_faq2.html#void-main
:-)

von Markus F. (mfro)


Lesenswert?

Yalu X. schrieb:
> Thomas M. schrieb:
>> Na eben wenn es aber um AVR geht,
>
> ... must du dir keine Sorgen machen:
>
> Die allermeisten AVR-Programm laufen sowieso in einer Endlosschleife.
> Der AVR-GCC (getestet mit 8.2.0) erkennt dies und lässt dann die
> Instruktionen für den Rückgabe des Funktionswerts weg, auch wenn main
> als int deklariert ist.

Da frag' ich mich gerade, was dein schlauer Compiler denn wohl 
wegoptimiert?

- die Warnung, daß eine als int deklarierte Funktion keinen Rückgabewert 
hat?
- das return-Statement, das Du gar nicht hingeschrieben hast?
- Oder die "statement not reached"-Warnung, weil Du eins hingeschrieben 
hast, das nie ausgeführt wird?

Die Compiler, die ich kenne (avr-gcc gehört zugegebenermaßen nicht dazu, 
aber Google hat gesagt, daß es da auch so ist) liefern Rückgabewerte 
(zumindest für integrale Typen) in Registern. In Registern steht am Ende 
einer Funktion üblicherweise was drin (ob gewollt oder nicht). Wie kann 
man das wegoptimieren?

(das gilt natürlich nicht für Register-saves und -restores, die man sich 
natürlich sparen kann, wenn man weiß, daß eine Funktion nie zurückkehrt)

von Thomas M. (Firma: https://img.favpng.com/23/21/3) (thomasmopunkt)


Lesenswert?

schön finde ich, wie meine einfachen Anfängerfragen doch öfter zu 
umfangreichen Diskussionen führe, was zeigt, das viele sich mit dieser 
durchaus recht unbedeutenden Frage, nie beschäftigt haben und die 
meisten es halt einfach nur tun weil es so ist :-)

von Axel S. (a-za-z0-9)


Lesenswert?

Markus F. schrieb:
> Yalu X. schrieb:
>> Thomas M. schrieb:
>>> Na eben wenn es aber um AVR geht,
>>
>> ... must du dir keine Sorgen machen:
>>
>> Die allermeisten AVR-Programm laufen sowieso in einer Endlosschleife.
>> Der AVR-GCC (getestet mit 8.2.0) erkennt dies und lässt dann die
>> Instruktionen für den Rückgabe des Funktionswerts weg, auch wenn main
>> als int deklariert ist.
>
> Da frag' ich mich gerade, was dein schlauer Compiler denn wohl
> wegoptimiert?

Alles, was nach der Endlosschleife in main() kommt.

> - die Warnung, daß eine als int deklarierte Funktion keinen Rückgabewert
> hat?

Kriegt man bei main() sowieso nicht. Das ist ein Sonderfall. Bilde dich 
mal weiter.

> - das return-Statement, das Du gar nicht hingeschrieben hast?

Dito. Auch das ist bei main() erlaubt.

> - Oder die "statement not reached"-Warnung, weil Du eins hingeschrieben
> hast, das nie ausgeführt wird?

Eine solche Warnung würde ich erwarten. Aber im Kontext deiner Frage: 
Warnungen werden natürlich nicht "wegoptimiert".

von Yalu X. (yalu) (Moderator)


Lesenswert?

Markus F. schrieb:
> Da frag' ich mich gerade, was dein schlauer Compiler denn wohl
> wegoptimiert?

Ohne Endlosschleife werden zwei Register mit dem Returnwert befüllt und
danach ein ret ausgeführt:

1
int main(void) {
2
  return 42;
3
}
1
main:
2
  ldi r24,lo8(42)
3
  ldi r25,0
4
  ret

Mit Endlosschleife wird die return-Anweisung wegoptimiert, da sie nie
erreicht werden kann:

1
int main(void) {
2
  for(;;);
3
  return 42;
4
}
1
main:
2
.L2:
3
  rjmp .L2

von Peter D. (peda)


Lesenswert?

Markus F. schrieb:
> Da frag' ich mich gerade, was dein schlauer Compiler denn wohl
> wegoptimiert?
1
int main( void )
2
{
3
  while(true){
4
    PORTB = 1;
5
  c4:  81 e0         ldi  r24, 0x01  ; 1
6
  c6:  85 b9         out  0x05, r24  ; 5
7
  c8:  fe cf         rjmp  .-4        ; 0xc6 <main+0x2>

von Markus F. (mfro)


Lesenswert?

Axel S. schrieb:
>> - die Warnung, daß eine als int deklarierte Funktion keinen Rückgabewert
>> hat?
>
> Kriegt man bei main() sowieso nicht. Das ist ein Sonderfall. Bilde dich
> mal weiter.

Versuche ich. Meine Kopie des C99-Standards behauptet allerdings (in 
Anhang - "informative" - I), daß Warnings nicht Teil des Standards sind 
und da also jeder machen kann, was er will: "An implementation may 
generate warnings in many situations, none of which are specified as 
part of this International Standard."

Ein Compiler, der vor was ganz anderem warnt, wäre also trotzdem 
konform.

von Egger (Gast)


Lesenswert?

Hans-Georg L. schrieb:
> Weil ein int die Größe eines MC Registers hat und der return Wert in
> einem Register an den Startup Code zurückgegeben wird.

1+

von Axel S. (a-za-z0-9)


Lesenswert?

Markus F. schrieb:
> Axel S. schrieb:
>>> - die Warnung, daß eine als int deklarierte Funktion keinen Rückgabewert
>>> hat?
>>
>> Kriegt man bei main() sowieso nicht. Das ist ein Sonderfall. Bilde dich
>> mal weiter.
>
> Versuche ich. Meine Kopie des C99-Standards behauptet allerdings (in
> Anhang - "informative" - I), daß Warnings nicht Teil des Standards sind

Das war nicht mein Punkt. Sondern daß es in C legal ist, wenn man main() 
mit einem int Rückgabewert definiert, dann aber kein return Statement im 
Code hat. Insofern gibt es für den Compiler keinen Grund, eine Warnung 
zu erzeugen.

von M. Н. (Gast)


Lesenswert?

Hans-Georg L. schrieb:
> Weil ein int die Größe eines MC Registers hat und der return Wert in
> einem Register an den Startup Code zurückgegeben wird. Du sparst mit
> einem Char überhaupt nichts.

Falsch! Ein int ist definiert als mindestend 16 bit breit. Deswegen hat 
dieser auf einem AVR beispielsweise auch 16 bit, was nicht in ein 
Register passt.

von Markus F. (mfro)


Lesenswert?

Axel S. schrieb:
> Sondern daß es in C legal ist, wenn man main()
> mit einem int Rückgabewert definiert, dann aber kein return Statement im
> Code hat.

Siehste, jetzt habe ich doch was gelernt. Im Standard steht tatsächlich:

"reaching the } that terminates the main function returns a value of 0."

Das habe ich wohl bis dato überlesen, danke.

von Vn N. (wefwef_s)


Lesenswert?

Thomas M. schrieb:
> Na eben wenn es aber um AVR geht, würde ja char reichen, klar geht es
> nicht un ein Byte hier oder dort..aber als Anfänger macht es wohl Sinn
> sowas zu hinterfragen und nicht einfach möglichen fehlerhaften
> Lehrmeinungen nachzulaufen

Das ist keine Meinung, das ist die Sprachdefinition von C.

Thomas M. schrieb:
> +Irgendwie regen sich bei C eigentlich alle immer über alles auf weil
> irgendwie immer alles falsch oder nicht so richtig richtig
> ist....

Muss man sich halt an den Standard halten, dann passts.
Wenn du dich an den Duden hälst und leserliches Deutsch produzierst, 
wird dich auch keiner mehr fragen ob du Legastheniker bist.

von Thomas M. (Firma: https://img.favpng.com/23/21/3) (thomasmopunkt)


Lesenswert?

"wird dich auch keiner mehr fragen ob du Legastheniker bist."

bin ich aber und nun?!
Dämlicher Kommentar, weißt Du aber sicher selber...hoffe ich...

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.