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 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.
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.
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.
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.
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
"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?
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.
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.
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
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
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.
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.
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...
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.
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 ;-)
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 ...
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.
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?
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.
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.
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.
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)
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 :-)
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".
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
intmain(void){
2
return42;
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:
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.
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+
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.
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.
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.
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.
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