int main (void) warum nicht char main (void)

#5695131
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.
#5695149
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.
Persönliche Seite #5695155
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.
#5695208
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.
#5695210
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
#5695212
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
Persönliche Seite #5695220
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.
Moderator #5695222
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.
(Firma: https://img.favpng.com/23/21/3) #5695236
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...
Gast #5695238
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
Gast #5695247
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
}
(Firma: https://img.favpng.com/23/21/3) #5695259
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 ;-)
Persönliche Seite #5695260
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 ...
Gast #5695287
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.
#5695320
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?
#5695332
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.
Gast #5695356
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.
#5695436
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)
#5695506
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".
Moderator #5695509
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
#5695554
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.
#5695729
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.
Gast #5695749
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.
#5695758
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.
#5695771
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.

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren