Forum: Mikrocontroller und Digitale Elektronik Warum "uint8_t" statt "char"


von Torsten B. (torty)


Lesenswert?

Hallo Gemeinde

Kann mir jemand erklären, warum mann bei Variablen Deklarationen in 
BeispielCode oft zB "uint8_t" statt "char" lesen kann ?

Weil es in der " stdint.h" so definiert ist ! Ja!
Aber warum weicht diese vom C-Standard ab ?

Danke
Torsten

: Gesperrt durch Moderator
von Peter II (Gast)


Lesenswert?

Torsten B. schrieb:
> BeispielCode oft zB "uint8_t" statt "char" lesen kann ?

weil für char nicht mal festgelegt ist ob es signed oder unsigned ist.

von unterscheidung (Gast)


Lesenswert?

Also ich benutze uint8_t für Variablen, die Zahlen aufnehmen und char 
für welche die Zeichen aufnehmen.

Dem µC bzw. Compiler ist das wohl total egal, aber ich finde es einfach 
passender z.B. die Laufvariable i als uint8_t zu deklarieren als als 
char...

von Ronny S. (duselbaer)


Lesenswert?

Weil ein uint8_t unsigned ist.
Und vor allem, weil ein uint8_t auf den ersten Blick deutlich macht, wie 
groß der Datentyp ist. Gerade bei plattformübergreifender Entwicklung 
ist das wichtig. Nicht überall ist ein int 32 Bit groß.

von Peter II (Gast)


Lesenswert?

Ronny Spiegel schrieb:
> Weil ein uint8_t unsigned ist.

was sagt das?

von (prx) A. K. (prx)


Lesenswert?

Torsten B. schrieb:
> Kann mir jemand erklären, warum mann bei Variablen Deklarationen in
> BeispielCode oft zB "uint8_t" statt "char" lesen kann ?

uint8_t       exakt 8 Bits ohne Vorzeichen.
uint_fast8_t  mindestens 8 Bits ohne Vorzeichen, laufzeitoptimiert.
char          Zeichen mit oder ohne Vorzeichen, 8 oder mehr Bits.

Bei plattformunabhängigem Code ist also uint_fast8_t sinnvoll, da 
uint8_t bei 16/32-Bit Prozessoren ineffizient sein kann.

von Peter D. (peda)


Lesenswert?

Torsten B. schrieb:
> Kann mir jemand erklären, warum mann bei Variablen Deklarationen in
> BeispielCode oft zB "uint8_t" statt "char" lesen kann ?

Hab ich noch nie gesehen, zeig mal ein Beispiel.
"uint8_t" hab ich nur statt "unsigned char" gesehen und da spart es 
deutlich Schreibarbeit.

von (prx) A. K. (prx)


Lesenswert?

Peter II schrieb:
> Ronny Spiegel schrieb:
>> Weil ein uint8_t unsigned ist.
>
> was sagt das?

Es stimmt, wenn damit wortwörtlich "ohne Vorzeichen" gemeint ist, nicht 
der Typ "unsigned int".

von (prx) A. K. (prx)


Lesenswert?

Vervollständigt:

uint8_t        exakt 8 Bits ohne Vorzeichen.
uint_fast8_t   mindestens 8 Bits ohne Vorzeichen, laufzeitoptimiert.
uint_least8_t  mindestens 8 Bits ohne Vorzeichen, platzoptimiert.
char           Zeichen mit oder ohne Vorzeichen, 8 oder mehr Bits.

uint_least8_t ergibt Sinn, wenn man eines Tages in Gefahr läufen könnte, 
eine Maschine zu erwischen, die keinen 8-Bit Datentyp unterstützt und 
folglich uint8_t nicht kennt.

von Florian T. (florian_t)


Lesenswert?

Also das versteh ich nicht. Ein char ist definiert als ein Zeichen 
(Byte) welches genau 8 Bit hat. Mir ist noch nie untergekommen dass ein 
char signed sein könnte. Vorallem wäre mal interessant: Wer kommt denn 
auf die Idee ein signed char zu verwenden? Und vorallem: Wo??

von Karl H. (kbuchegg)


Lesenswert?

Florian Trück schrieb:
> Also das versteh ich nicht. Ein char ist definiert als ein Zeichen
> (Byte) welches genau 8 Bit hat. Mir ist noch nie untergekommen dass ein
> char signed sein könnte.

Was nicht heißt, das es das nicht gibt.
Du brauchst nur den gcc mit der entsprechenden Option aufrufen und schon 
sind deine char alle signed.

von Florian T. (florian_t)


Lesenswert?

Karl Heinz Buchegger schrieb:
> Was nicht heißt, das es das nicht gibt.
> Du brauchst nur den gcc mit der entsprechenden Option aufrufen und schon
> sind deine char alle signed.

Das mag ja sein, aber wozu braucht man ein signed char mit dem 
Wertebereich (-127) - (127) ?

von (prx) A. K. (prx)


Lesenswert?

Florian Trück schrieb:
> Ein char ist definiert als ein Zeichen
> (Byte) welches genau 8 Bit hat.

Nein.

> Mir ist noch nie untergekommen dass ein char signed sein könnte.

Das war früher ziemlich verbreitet und ist irgendwo bestimmt noch so.

> Vorallem wäre mal interessant: Wer kommt denn
> auf die Idee ein signed char zu verwenden?

Die erste C Implementierung, also die auf einer DEC PDP-11. Deren 8-Bit 
Operationen arbeiteten nämlich implizit mit Vorzeichen. Bei 
nachfolgenden Implementierungen wurde es lange Zeit ebenso gehandhabt, 
auch wenn es ohne Vorzeichen sinnvoller gewesen wäre.

von Karl H. (kbuchegg)


Lesenswert?

Florian Trück schrieb:
> Karl Heinz Buchegger schrieb:
>> Was nicht heißt, das es das nicht gibt.
>> Du brauchst nur den gcc mit der entsprechenden Option aufrufen und schon
>> sind deine char alle signed.
>
> Das mag ja sein, aber wozu braucht man ein signed char mit dem
> Wertebereich (-127) - (127) ?

Es geht nicht darum, ob du oder ob man das braucht. Es geht darum, was 
dein Compilerbauer für eine gute Idee auf einer bestimmten Plattform 
gehalten hat, bzw. was die CPU an Assemblerbefehlen mitbringt.


Im Ernst. Wo liegt denn das Problem?


uint8_t     für 'kleine Zahlen' ohne Vorzeichen.
            (Im Volksmund auch Byte genannt)

int8_t      für 'kleine Zahlen' mit Vorzeichen.
            zb Schleifensteuerungen die auch mal negativ werden können

char        für alles was mit Textverarbeitung zu tun hat.


Ist doch ganz einfach. Und zusätzlich hat man auch noch im Programm eine 
schöne Trennung, wo man es mit Textverarbeitung und wo man es mit Bytes 
im weitesten Sinne zu tun hat. Denn Textverarbeitung impliziert 
zusätlich noch, dass Strings eine terminierende \0 enthalten.

von Peter II (Gast)


Lesenswert?

Florian Trück schrieb:
> Mir ist noch nie untergekommen dass ein
> char signed sein könnte.

im gcc ist es immer signed
1
#include <stdio.h>
2
int main() {
3
  char c = 0xff;
4
  int i = c;
5
  printf("test:%d\n", i );

na was kommt raus?

von DirkB (Gast)


Lesenswert?

Florian Trück schrieb:
> Also das versteh ich nicht. Ein char ist definiert als ein Zeichen
> (Byte) welches genau 8 Bit hat.

Mindestens 8 Bit. Es könne nauch mehr sein.

Florian Trück schrieb:
> Mir ist noch nie untergekommen dass ein
> char signed sein könnte. Vorallem wäre mal interessant: Wer kommt denn
> auf die Idee ein signed char zu verwenden? Und vorallem: Wo??
Da ASCII nur ein 7-Bit Code ist, reicht das signed da vollkommen aus.

Es ist im C-Standard nicht festgelegt ob char signed oder unsigned ist.
Ich erinnere mich auch an keinen Compiler, der unsigned wäre. (oder es 
ist sooo lange her)

von Peter D. (peda)


Lesenswert?

Florian Trück schrieb:
> Das mag ja sein, aber wozu braucht man ein signed char mit dem
> Wertebereich (-127) - (127) ?

Man braucht es genauso dringend, wie einen Knopf an der Backe, aber es 
wurde von den C-Erfindern nun einmal so festgelegt.

Es fällt einem auch regelmäßig auf die Nase, z.B. wenn man in einem 
Stream Text und Zahlenwerte überträgt bzw. manche Programme können 
deshalb keine Zeichen >127 darstellen.

von Ronny S. (duselbaer)


Lesenswert?

Florian Trück schrieb:
> Also das versteh ich nicht. Ein char ist definiert als ein Zeichen
> (Byte) welches genau 8 Bit hat. Mir ist noch nie untergekommen dass ein
> char signed sein könnte. Vorallem wäre mal interessant: Wer kommt denn
> auf die Idee ein signed char zu verwenden? Und vorallem: Wo??

Der Visual Studio Compiler, den ich in der Arbeit verwende(n muss). Ein

   char x = 254;

spuckt eine entsprechende Warnung aus, wohingegen

   char x = -12;

anstandslos funktioniert.

Mit Typdefinitionen, die explizit angeben, ob ein Typ vorzeichenbehaftet 
ist oder nicht, treten solche Sachen gar nicht erst auf.

von Kaj (Gast)


Lesenswert?

Hey Ho,

Ich weiß von Atmel Studio 6 das dort ein char default mäßig als unsigned 
char betrachtet wird, kann man aber in den Projekteinstellungen ändern.
Ich benutze in meinen Projekten für 1-Byte Variablen immer den char-Typ 
und hatte damit noch nie Probleme. Und das bisschen was man da an 
Schreibarbeit sparen könnte...naja, ist wohl ansichts sache. ;)
In .Net soll ein char wohl 16-Bit haben.
Ich glaube allerdings das wir uns hier auf C/C++ beziehen. Weiterhin 
denke ich das "Platformunabhängigkeit" auf einem µC ziemlich Latte ist, 
solange man sicht nicht auf der Himbeere befindet bzw. sonst irgendein 
OS benutzt.

In diesem Sinne, Grüße

von Karl H. (kbuchegg)


Lesenswert?

Ronny Spiegel schrieb:

> Der Visual Studio Compiler, den ich in der Arbeit verwende(n muss). Ein
>
>    char x = 254;
>
> spuckt eine entsprechende Warnung aus, wohingegen
>
>    char x = -12;
>
> anstandslos funktioniert.
>
> Mit Typdefinitionen, die explizit angeben, ob ein Typ vorzeichenbehaftet
> ist oder nicht, treten solche Sachen gar nicht erst auf.


Auf die Nase fällt man zb dann, wenn der char in einem Vergleich 
vorkommt. Denn da spielt es dann eine Rolle

  char c = 254;

  if(  c == 254 )
    printf( "juhu" );

auf einem Compiler, bei dem ein char signed ist, wird der if nie 
genommen. Und das Rätselraten ist groß, warum nicht.

Mit expliziten uint8_t, int8_t, char (je nach Anwendungszweck) gibt es 
diese Probleme erst gar nicht.

von Tach (Gast)


Lesenswert?

Kaj schrieb:
> In .Net soll ein char wohl 16-Bit haben.

Nicht nur da. Verwende z.B. mal die Piccolo-Serie von TI!
Da ist das kleinste was Du bekommst eine 16 Bit Variable ;-)

von (prx) A. K. (prx)


Lesenswert?

Peter Dannegger schrieb:
> Man braucht es genauso dringend, wie einen Knopf an der Backe, aber es
> wurde von den C-Erfindern nun einmal so festgelegt.

Es war nicht festgelegt. Von Anfang an war offen, ob char mit oder ohne 
Vorzeichen implementiert ist. Es war einfach nur üblich, weil "schon 
immer so gemacht".

von (prx) A. K. (prx)


Lesenswert?

Kaj schrieb:
> denke ich das "Platformunabhängigkeit" auf einem µC ziemlich Latte ist,

Würde ich nicht sagen. Beispiel: Im Code für den Temperatursensor 
DS18S20 ist ausschliesslich die Pinwackelei direkt hardwareabhängig, und 
das sind sehr wenige Operationen. Folglich kann fast der gesamte Code 
wiederverwendet werden.

von Karl H. (kbuchegg)


Lesenswert?

Schon mal überlegt, warum

  char c;
  while( (c = getchar()) != EOF )
     ...

in C überhaupt wie angedacht funktioniert?

wenn c ein unsigned char wäre, funktioniert es nämlich nicht mehr :-)

von (prx) A. K. (prx)


Lesenswert?

Es funktioniert so auch nicht wie angedacht, egal ob signed oder nicht.

Der korrekte und überall zu findende Code ist
  int c;
  while( (c = getchar()) != EOF )
     ...
und genau dieser Aspekt gehört m.W. zum Grundwissen in C. Dass getchar 
bei den üblichen Plattformen tatsächlich 257 mögliche Werte zurück gibt 
und solche Zeichen deshalb nicht als char definiert werden dürfen.

Die Perversion dabei ist, dass auf Plattformen, bei denen "char" mit 
Vorzeichen definiert und EOF dennoch wie üblich -1 ist, getchar() die 
Werte 0..255 zurück gibt, nicht -128..127.

Wirklich verstehen muss man das nicht. Einfach akzeptieren. ;-)

von Marco M. (marco_m)


Lesenswert?

Peter II schrieb:
> Florian Trück schrieb:
>> Mir ist noch nie untergekommen dass ein
>> char signed sein könnte.

Vermutlich sitzt du genau in diesem Augenblick vor einem Rechner bei dem 
das genau so ist.


>
> im gcc ist es immer signed

Das hat nichts mit gcc zu tun, sondern mit der Platform. x86 und x86_64 
haben z.B. üblicherweise signed char, während ARM, MIPS und PowerPC 
unsigned char haben. Der Grund für solche Unterschiede sind z.T. 
historisch und oftmals Performancefragen. Einige Architekturen müssten 
z.B. Konvertierungen durchführen um chars auf eine andere Weise zu 
unterstützen.

In C/C++ sind die Eigenschaften der intrinsischen Datentypen aus 
Performancegründen von der zugrundeliegenden Architektur bestimmt und 
man geht normalerweise davon aus, dass ein kompetenter Programmierer mit 
signenness/unsignedness von char, den plattformspezifischen Größen von 
short, int, long und all dem anderen Kram umgehen kann.

von Karl H. (kbuchegg)


Lesenswert?

A. K. schrieb:
> Es funktioniert so auch nicht wie angedacht, egal ob signed oder nicht.

Ja, ok.
'funktioniert' ist zu hoch gegriffen.
Aber bei 7-Bit ASCII und signed char kommt man damit durch.
(Nicht das ich das propagieren würde. Gott bewahre.)

von Marco M. (marco_m)


Lesenswert?

Korrektur: MIPS hat unter Debian und NetBSD signed char. Sparc hat 
ebenfalls signed char, s390 dagegen unsigned char.

von Peter D. (peda)


Lesenswert?

Nochn schönes Beispiel für die "signed char" Fallgrube ist auch das 
Ummappen der deutschen Umlaute für ein LCD. Wenn man nicht nach unsigned 
castet, funktioniert es nicht.

Wenn man aber zur Umgehung all dieser Probleme die Stringpuffer als 
unsigned anlegt, meckert einem der AVR-GCC ständig die Hucke voll.

von Sam P. (Gast)


Lesenswert?

Torsten B. schrieb:
> Aber warum weicht diese vom C-Standard ab ?

Zum Rest wurde ja schon alles gesagt, aber man sollte vielleicht noch 
erwähnen, dass stdint.h und damit uint8_t natürlich voll und ganz dem 
C-Standard entsprechen.

Das ist ja gerade das schöne, dass man endlich mal ohne große 
Verrenkungen Datentypen hat, bei denen man sich drauf verlassen kann, 
dass sie einen klar bestimmten numerischen Umfang und Platzbedarf haben. 
Bei "char" drängt sich einem das noch nicht so auf, wobei 
signed-vs.-unsigned auch ein echtes Arschloch sein kann.

Noch viel mehr Spaß hat man mit "int" und "long". Ob das dann 32 oder 64 
oder gar nur 16 Bit sind, hängt von CPU, Betriebssystem, 
32-/64-Bittigkeit des Betriebssystems, gewähltem Speichermodell 
(x86/x86_64/x32) und der Mondphase ab.

Und weil der ursprüngliche C-Standard absichtlich so viele 
Unwägbarkeiten enthielt (man dachte das ist ne super Idee: jede 
Plattform nimmt was am "besten" für sie ist), und man gelernt hat, dass 
der Ansatz nicht so toll funktioniert wie man dachte, gibt es eben 
inzwischen die zusätzlichen Datentypen in stdint.h.

von Achim M. (minifloat)


Lesenswert?

Ich schreibe uint8_t, weil ich die Trivialnamen hasse. Man sieht sofort, 
dass das 8bit sind. mf

von Rolf M. (rmagnus)


Lesenswert?

Florian Trück schrieb:
> Mir ist noch nie untergekommen dass ein char signed sein könnte.

Mir schon oft. Ist auch konsistenter, da alle anderen Integer-Typen ja 
auch signed sind, wenn nicht explizit ein 'unsigned' davor steht. Da man 
damit aber eh niemals rechnet, sondern nur Zeichen drin abspeichert, ist 
es auch völlig wurscht, ob's nun signed oder unsigned ist.

Peter Dannegger schrieb:
> Nochn schönes Beispiel für die "signed char" Fallgrube ist auch das
> Ummappen der deutschen Umlaute für ein LCD. Wenn man nicht nach unsigned
> castet, funktioniert es nicht.
>
> Wenn man aber zur Umgehung all dieser Probleme die Stringpuffer als
> unsigned anlegt, meckert einem der AVR-GCC ständig die Hucke voll.

Deswegen macht man das ja auch nicht so. Alle Stringpuffer sind char. 
Und an einer einzigen Stelle, wo man den Wert dann in ein Register 
schreibt, macht man die Konvertierung.
Es gibt eben getrennte Typen für "Zeichen" und für "Bytes", und char ist 
eben der Typ ausschließlich für Zeichen. Das ist auch keine Eigenheit 
von C. Auch bei den meisten anderen Sprachen muß ich eine Konvertierung 
durchführen, wenn ich ein Zeichen habe und dieses als Bytewert nutzen 
will.
Wenn in C unsigned char und signed char stattdessen unsigned byte und 
signed byte heißen würden, char ohne signed und unsigned aber seinen 
Namen behalten würde, wäre das wahrscheinlich jedem sofort klar.

Joachim минифлоть schrieb:
> Ich schreibe uint8_t, weil ich die Trivialnamen hasse. Man sieht sofort,
> dass das 8bit sind. mf

Allerdings gibt es den Fall, daß die Variable zwingend exakt 8 Bit groß 
sein muß, gar nicht so oft.

von W.S. (Gast)


Lesenswert?

Sam P. schrieb:
> Und weil der ursprüngliche C-Standard absichtlich so viele
> Unwägbarkeiten enthielt (man dachte das ist ne super Idee: jede
> Plattform nimmt was am "besten" für sie ist), und man gelernt hat, dass
> der Ansatz nicht so toll funktioniert wie man dachte, gibt es eben
> inzwischen die zusätzlichen Datentypen in stdint.h.

Tja, diese Denkweise ist halt C. Besser wäre es gewesen, den bereits 
existierenden Wörtern endlich mal ne saubere Bedeutung zu geben, damit 
man sich drauf verlassen kann, daß int eben 16 Bit und long 32 Bit ist, 
egal auf welcher Maschine. Diese an den Haaren herbeigezogenen 
Pseudotypen 'x'int'n'_t sind eklig zu lesen und kein Compiler kennt sie 
wirklich. stattdessen werden sie per #define überall wieder vom 
Preprozessor auf die althergebrachten Typen char, int, long 
zurückübersetzt, bevor der Compiler sie zu lesen bekommt. Wozu also 
dieser unleserliche Mumpitz? Wenn überhaupt, wäre das ne Sache, die als 
echter Datentyp direlt in den Compiler gehört hätte.


Aber laßt mal, woanders wird mittlerweile der gleiche Murks gemacht. 
Siehe 'char' und chr(x) im aktuellen Delphi XE3. Wahrscheinlich haben 
dort auch C-Programmierer angefangen...

W.S.

von (prx) A. K. (prx)


Lesenswert?

Du solltest auf PL/I umsteigen. ;-)

http://www.uni-muenster.de/ZIV.EberhardSturm/PL1andC.html

von Karl H. (kbuchegg)


Lesenswert?

W.S. schrieb:

> Tja, diese Denkweise ist halt C. Besser wäre es gewesen, den bereits
> existierenden Wörtern endlich mal ne saubere Bedeutung zu geben, damit
> man sich drauf verlassen kann, daß int eben 16 Bit und long 32 Bit ist,
> egal auf welcher Maschine.

Tja.
Das 'Problem' mit den ISO-Gremien ist, dass sie nichts mehr ändern (oder 
nur mit vorgehaltener Waffe), wenn etwas mal im Standard steht.


Die Idee war es halt, dass ein int sowas wie die Leib- und Magengröße 
einer CPU sein sollte. Gewisse Mindeststandards werden garantiert. Alles 
was darüber hinausgeht, legt der Compilerbauer und/oder die CPU fest.


War nicht unbedingt die stärkste Idee, ermöglicht aber auf der anderen 
Seite Programme (die sich nur auf die zugesicherten Mindesteigenschaften 
verlassen), vom kleinen 8-Bitter bis hinauf zu einem Supercomputer 
unverändert laufen zu lassen und auf jeder Maschine wird der jeweils 
schnellste Code dafür erzeugt.

von Rolf M. (rmagnus)


Lesenswert?

W.S. schrieb:
> Tja, diese Denkweise ist halt C. Besser wäre es gewesen, den bereits
> existierenden Wörtern endlich mal ne saubere Bedeutung zu geben, damit
> man sich drauf verlassen kann, daß int eben 16 Bit und long 32 Bit ist,
> egal auf welcher Maschine.

Es gibt auch DSPs mit 24 Bit natürlicher Wortbreite. Darauf wäre C dann 
nicht mehr sinnvoll möglich.

> Diese an den Haaren herbeigezogenen Pseudotypen 'x'int'n'_t sind eklig zu
> lesen

Ich finde sie eigentlich sehr gut zu lesen, weil der Name schon genau 
verrät, was es ist.

> und kein Compiler kennt sie wirklich.

Das ist aber die Schuld der Compiler-Hersteller und nicht die von C. 
Dort ist das seit 14 Jahren bereits genormt, und jeder ISO-konforme 
Compiler muß das mit dabei haben.

> Wenn überhaupt, wäre das ne Sache, die als echter Datentyp direlt in den
> Compiler gehört hätte.

Wozu? Welchen Vorteil hätte das denn?

von (prx) A. K. (prx)


Lesenswert?

Rolf Magnus schrieb:
> Wozu? Welchen Vorteil hätte das denn?

Ich hatte oben nicht zufällig PL/I genannt. Da wird die Genauigkeit per 
Stellenzahl direkt in die Deklaration geschrieben. Wenn man also eine 
binäre Variable mit 13 Bits ohne Vorzeichen braucht, dann schreibt man 
das einfach da rein:
  dcl x fixed bin(13) unsigned;
Was der Compiler intern daraus macht ist dann seine Sache.

Dummerweise waren PL/I Compiler anfangs äusserst unhandliche Kolosse, 
weil da noch ein paar mehr gute und schlechte Ideen drin sind. So wie 
Unix als Gegenentwurf zu Multics entstand - was in PL/I programmiert war 
- entstand C als Gegenentwurf zu PL/I. Als Sprache, die auch auf kleinen 
Computern umgänglich war, grad wie Unix ein Betriebssystem für kleine 
Computer war.

PS: Ich finde PL/I insgesamt grauslich. Aber es illustriert den Punkt.

von _t (Gast)


Lesenswert?

Joachim минифлоть schrieb:
> Ich schreibe uint8_t, weil ich die Trivialnamen hasse. Man sieht sofort,
> dass das 8bit sind. mf

Da setze ich noch eine drauf. Ich benutze bei uC nie die Namen mit "_t", 
sondern nur U8, S8, U16 ...

von Peter II (Gast)


Lesenswert?

_t schrieb:
> Da setze ich noch eine drauf. Ich benutze bei uC nie die Namen mit "_t",
> sondern nur U8, S8, U16 ...

wie wie sehen signed aus?

von Sam P. (Gast)


Lesenswert?

W.S. schrieb:
> Tja, diese Denkweise ist halt C. Besser wäre es gewesen, den bereits
> existierenden Wörtern endlich mal ne saubere Bedeutung zu geben, damit
> man sich drauf verlassen kann, daß int eben 16 Bit und long 32 Bit ist,
> egal auf welcher Maschine.

Sie haben eine saubere Bedeutung, nur nicht die, die du gerne hättest. 
"int" sagt: "Gib mir eine Ganzzahl, mit der ich sinnvoll auf dieser 
Machine arbeiten kann." Weder macht es Sinn, einen 8-Bit-µC zu 32 Bit 
ints zu zwingen, noch bringt es irgendeinen Vorteil, Rechner mit vielen 
Gigabytes RAM (und entsprechend vielen Datensätzen etc. im Programm) bei 
65535/32767 zu deckeln. Die Grundidee hinter "int" ist gut, sie macht 
nur nicht das, was viele damit versuchen zu erreichen.

Aber es gibt da diese anderen Datentypen im C-Standard, die ebenfalls 
eine saubere Bedeutung haben und so definiert sind wie du es möchtest. 
Wie hiessen die nur nochmal?


> Diese an den Haaren herbeigezogenen
> Pseudotypen 'x'int'n'_t sind eklig zu lesen und kein Compiler kennt sie
> wirklich. stattdessen werden sie per #define überall wieder vom
> Preprozessor auf die althergebrachten Typen char, int, long
> zurückübersetzt, bevor der Compiler sie zu lesen bekommt.

stdint.h ist integraler Bestandteil der C-Laufzeitumgebung. Es sind 
keine Pseudotypen und es findet keine Textersetzung im Präprozessor 
statt. Es sind ordentlich per typedef definierte Typen, die genau auf 
den Compiler zugeschnitten sind.

Nur weil man eine Headerdatei einbinden muss, ist das noch lange kein 
Fremdkörper. Nenne mir eine Sprache, in der du nicht einige Bestandteile 
der Standard-Laufzeitumgebung über eine Import-Deklaration einbinden 
musst, wenn du sie nutzen willst. Dein offenbar bevorzugtes Delphi macht 
es doch nicht anders.


> Wozu also
> dieser unleserliche Mumpitz? Wenn überhaupt, wäre das ne Sache, die als
> echter Datentyp direlt in den Compiler gehört hätte.

Ich finde ein 16-Bit "int" ziemlich unleserlich. Selbst beim ATMega, wo 
16-Bit-int Sinn macht, hab ich mich manchmal ertappt, wie ich ungewollt 
einen Overflow produziert habe. Ein int16_t zeight dagegen deutlich und 
direkt, was man da gerade deklariert. Es ist standardisiert, jeder 
Compiler aus diesem Jahrtausend versteht es, und es bedeutet immer das 
gleiche.

Viel schlimmer ist die Pest an Bibliotheken und APIs, die alle noch 
nicht begriffen haben, dass es stdint.h gibt und überall funktioniert, 
und dann hat man in einem einzigen Programm plötzlich 4 verschiedene 
Namen plus "int" für eine vorzeichenbehaftete 32-Bit-Ganzzahl. Das ist 
unleserlich...

_t schrieb:
> Da setze ich noch eine drauf. Ich benutze bei uC nie die Namen mit "_t",
> sondern nur U8, S8, U16 ...

... dankeschön. Hoffentlich muss ich nie deinen Code warten.

von Auch egal (Gast)


Lesenswert?

Peter II schrieb:
> _t schrieb:
>> Da setze ich noch eine drauf. Ich benutze bei uC nie die Namen mit "_t",
>> sondern nur U8, S8, U16 ...
>
> wie wie sehen signed aus?

_t schrieb:
> sondern nur U8, S8, U16 ...
                  ^^

von amateur (Gast)


Lesenswert?

Ein ganzer Sack voll Irrtümer resultiert aus der Unkenntnis der 
C-Datentypen.
Das ist allerdings verständlich, da der Hauptdatentyp von "C" ein Witz 
ist.
Ich musste mal lernen: Integer ist der "natürliche" Datentyp des 
Rechners.
Keine Ahnung ob es zu 4 Bit-Zeiten auch schon jemanden mit Namen Integer 
gab.
Anno 8080/86/186 (Z80, 68xx und wie sie alle hießen) waren das 8 Bit.
Später bekamen "Rechners" Zuwachs und das Kind war plötzlich 16 Bit 
breit. Das hüpfende Komma aber war - das Baby hieß auch Integer. 
Irgendwo war hier die Phantasie in Sachen Namensgebung verschütt 
jegangen. Heute streiten sich die Gelehrten, ob dem Baby die 32-er oder 
die 64-er Klamotten passen - es geht natürlich um (Trommelwirbel) 
Integer.

Etwas aber hat all das Überlebt und das ist der Datentyp char.
Ohne Vornamen oder mit signed davor ist er von -128 über 0 bis 127 
spezifiziert. Heißt er aber unsigned, so geht er von 0 bis 255.

Damit das Ganze aber nicht so langweilig wird wurden, z.T. weil man 
bestimmte Genauigkeiten benötigte, immer neue Datentypen geschaffen. 
Vielleicht aber auch, weil man sich die ganzen Namen nicht mehr merken 
konnte.
byte, short, word, longint u.s.w. Zum Teil mit, zum Teil ohne Vornamen.

Damit der Begriff: "Lebenslanges Lernen" auch mit Inhalt gefüllt wird, 
sind dann die Hardwarenahen Buben und Mädels dazu übergegangen so 
"C"-Krücken wie "uint8_t" oder "uint16_t" in die Welt zu setzen. Keine 
Ahnung ob sie das Benötigten oder ob sie glaubten das wir alle von 
Alzheimer befallen sind.

Also beteiligen Sie sich alle an dem Wettbewerb: "Wer findet einen 
Begriff für den neuen Datentypen mit 127 Bit Breite plus Zusatzzahl".

von (prx) A. K. (prx)


Lesenswert?

amateur schrieb:
> Ohne Vornamen oder mit signed davor ist er von -128 über 0 bis 127
> spezifiziert.

Ohne Vornamen ist nicht spezifiziert ob signed oder unsigned.

Zudem gibt es mittlerweile 3 formal verschiedene char Typen, nämlich
   char
   signed char
   unsigned char
wovon zwar 2 einen identischen Wertebereich haben, aber dennoch als 
separate Typen behandelt werden. Was bei Pointern eine Rolle spielt:
   char            c;
   signed char     *scp = &c;
   unsigned char   *ucp = &c;
führt mit -Wall zu
   2: warning: pointer targets in initialization differ in signedness
   3: warning: pointer targets in initialization differ in signedness

von amateur (Gast)


Lesenswert?

@A.K.
Ich habe in meinem ganzen Leben noch keinen signed char verwendet. Dafür 
sind mir meine Fingerkuppen einfach zu schade. Aus diesem Grunde stellt 
sich das Problem, für mich, auch nicht.
Natürlich: Wenn ich dem einen Kind den Namen "Hans" gebe und dem Anderen 
den Namen "Karl", so muss der Compiler meckern, wenn ich die Behauptung 
aufstelle: Hans = Karl;
Für mich gilt aber, bis zum Beweis des Gegenteils: char = signed char;
Egal was ein Compiler dazu zu sagen hat.

von Karl H. (kbuchegg)


Lesenswert?

amateur schrieb:
> Ein ganzer Sack voll Irrtümer resultiert aus der Unkenntnis der
> C-Datentypen.

Wie du gerade eindrucksvoll unter Beweis stellst.

von Sam P. (Gast)


Lesenswert?

amateur schrieb:
> Ich musste mal lernen: Integer ist der "natürliche" Datentyp des
> Rechners.

Du möchtest also keinen Datentyp haben, der für die Zielmaschine optimal 
ist und als allgemeiner Ganzzahl-Datentyp sinnvoll bzw. ausreichend ist?


amateur schrieb:
> Anno 8080/86/186 (Z80, 68xx und wie sie alle hießen) waren das 8 Bit.

Nicht für C. Ein "int" ist schon immer wenigstens 16 Bit gewesen, darf 
aber beliebig groß werden. 8 Bit "int" wäre dann doch etwas zu nutzlos.


amateur schrieb:
> Damit der Begriff: "Lebenslanges Lernen" auch mit Inhalt gefüllt wird,
> sind dann die Hardwarenahen Buben und Mädels dazu übergegangen so
> "C"-Krücken wie "uint8_t" oder "uint16_t" in die Welt zu setzen. Keine
> Ahnung ob sie das Benötigten oder ob sie glaubten das wir alle von
> Alzheimer befallen sind.

Du möchtest also nicht in der Lage sein, Präzision bzw. Speicherbedarf 
von Daten genau spezifizieren zu können, wenn es nötig ist?


Junge, junge, was du dir wohl für Datentypen wünschst. Leider kannst du 
dir für den 8080 nix mehr wünschen, die Geschichte ist geschrieben. Aber 
wenn wir dann die Zeitmaschine erfinden, dann kannst du es ja besser 
machen. 64-Bit Integer sind auf dem 4004 bestimmt ein Kassenschlager.

Ach was, ich steig da selbst rein und erfinde für C einfach ein Haufen 
Typen die klar definiert sind, in offiziellen Standards, die aber keiner 
liest. Ich nenn die dann "int", "short" und so weiter, nur um dich zu 
ärgern. :)

von Sam P. (Gast)


Lesenswert?

amateur schrieb:
> Ohne Vornamen oder mit signed davor ist er von -128 über 0 bis 127

Ach so, verlass dich auf die "-128" nicht allzusehr. Nirgendwo wird 
verlangt, dass negative Zahlen im Zweierkomplement dargestellt werden. 
Einerkomplement ist genauso erlaubt wie Zahl+Vorzeichenbit. Das macht 
natürlich keiner, weil praktisch jedes nichttriviale C-Programm dann 
nicht mehr funktioniert, aber erlaubt wäre es. Und auf irgendwelchen 
speziellen µCs/DSPs mag das sogar seinen Sinn haben.

von Rolf M. (rmagnus)


Lesenswert?

amateur schrieb:
> Für mich gilt aber, bis zum Beweis des Gegenteils: char = signed char;
> Egal was ein Compiler dazu zu sagen hat.

Lol. Interessante Herangehensweise.

Sam P. schrieb:
> Einerkomplement ist genauso erlaubt wie Zahl+Vorzeichenbit. Das macht
> natürlich keiner, weil praktisch jedes nichttriviale C-Programm dann
> nicht mehr funktioniert, aber erlaubt wäre es.

Warum sollten Programme dann nicht mehr funktionieren?

von amateur (Gast)


Lesenswert?

>Du möchtest also nicht in der Lage sein, Präzision bzw. Speicherbedarf
>von Daten genau spezifizieren zu können, wenn es nötig ist?

Es werden ja keine neuen Datentypen geschaffen sondern neue Namen.
Wenn ich mal die Krabbelkommazahlen außen vor lasse, hat sich seit char, 
word, int oder longint nichts neues mehr ergeben. Konstrukte wie 
uint8_t, uint16_t oder der große Bruder uint32_t sind ja nix als neue 
Namen für alte Kollegen.

von (prx) A. K. (prx)


Lesenswert?

amateur schrieb:
> uint8_t, uint16_t oder der große Bruder uint32_t sind ja nix als neue
> Namen für alte Kollegen.

Ja und? Was machen Schlüsselworte besser als Typedefs?

von (prx) A. K. (prx)


Lesenswert?

Rolf Magnus schrieb:
> Warum sollten Programme dann nicht mehr funktionieren?

Die negative Null dürfte für gewisse Irritationen gut sein.

von Andreas D. (rackandboneman)


Lesenswert?

"Ach so, verlass dich auf die "-128" nicht allzusehr. Nirgendwo wird
verlangt, dass negative Zahlen im Zweierkomplement dargestellt werden.
Einerkomplement ist genauso erlaubt wie Zahl+Vorzeichenbit. Das macht
natürlich keiner, weil praktisch jedes nichttriviale C-Programm dann
nicht mehr funktioniert, aber erlaubt wäre es. Und auf irgendwelchen
speziellen µCs/DSPs mag das sogar seinen Sinn haben."

Die Frage ist vor allem wieviel zu Bruch geht wenn man die Annahme dass 
der Zahlenwert 0 intern bei jedem numerischen Typ 
0x00/0x0000/0x00000000/... entspricht - und damit selbst bei brutalstem 
Type Punning einem "false"! - aushebelt.

von Johnny B. (johnnyb)


Lesenswert?

Kaj schrieb:
> In .Net soll ein char wohl 16-Bit haben.

Das kommt daher, weil in .NET für Strings normalerweise nicht ASCII zum 
Einsatz kommt, sondern Unicode bzw. UTF-16.

http://de.wikipedia.org/wiki/Unicode
http://de.wikipedia.org/wiki/UTF-16

von Rolf M. (rmagnus)


Lesenswert?

amateur schrieb:
>>Du möchtest also nicht in der Lage sein, Präzision bzw. Speicherbedarf
>>von Daten genau spezifizieren zu können, wenn es nötig ist?
>
> Es werden ja keine neuen Datentypen geschaffen sondern neue Namen.

Natürlich. Was sollte es auch bringen, komplett neue Typen in die 
Sprache aufzunehmen, die exakt gleich wie die alten sind, außer daß sie 
halt andere Namen haben?

> Wenn ich mal die Krabbelkommazahlen außen vor lasse, hat sich seit char,
> word, int oder longint nichts neues mehr ergeben. Konstrukte wie
> uint8_t, uint16_t oder der große Bruder uint32_t sind ja nix als neue
> Namen für alte Kollegen.

Ein uint32_t ist garantiert 32 Bit groß, ein int nicht.

von W.S. (Gast)


Lesenswert?

Sam P. schrieb:
> Sie haben eine saubere Bedeutung, nur nicht die, die du gerne hättest.
> "int" sagt: "Gib mir eine Ganzzahl, mit der ich sinnvoll auf dieser
> Machine arbeiten kann." Weder macht es Sinn, einen 8-Bit-µC zu 32 Bit
> ints zu zwingen, noch bringt es irgendeinen Vorteil, Rechner mit vielen
> Gigabytes RAM (und entsprechend vielen Datensätzen etc. im Programm) bei
> 65535/32767 zu deckeln. Die Grundidee hinter "int" ist gut, sie macht
> nur nicht das, was viele damit versuchen zu erreichen.

Du hast ne ziemlich seltsame Denkweise, die ich nicht teile.
Als Programmierer muß man sich auf die verwendeten Datentypen verlassen 
können, was in C nicht der Fall ist. Natürlich brauche ich auch auf 
einem 8 Bit uC 32 Bit Integerzahlen, gelegentlich auch int64, und auch 
auf der größten und dicksten Maschine ist es öfter als du denkst nötig, 
Integers bei 16 Bit "zu deckeln", wenn die Daten nämlich in Strukturen 
hineinpassen müssen, die von anderswo vorgegeben sind.

Mir ist ein bissel rätselhaft, wie du zu deinen Auffassungen kommst, 
deswegen hier ein paar Beispiele, damit du merkst, worum es geht:

Fall 1: Ich will das Ergebnis eines ADC's lesen. z.B. AD7714. Kommt bei 
Leuten, die mit Mikrocontrollern zu tun haben vor, sowas. Was kann ich 
dazu nehmen? int  oder long? Natürlich nehme ich long, weil das am 
wahrscheinlichsten die 24 Bit aufnehmen kann, die der IC ausgibt. Auf 
manchen Zielsystemen könnte ich auch int nehmen, aber wer garantiert mir 
das? Merkst du was? Wohldefinierte Datentypen sind für saubere und 
portable Programmierung wichtiger als die Befindlichkeit einer Maschine.

Fall 2: Ich will Daten auf eine SD-Karte schreiben und muß dazu die 
SD-Karte ansprechen, also initialisieren, die diversen Parameterblöcke 
auslesen, dann ein Filesystem aufsetzen usw. Natürlich richtet sich auch 
hier kein SD-Karten-Hersteller nach den Befindlichkeiten des verwendeten 
uC und auch kein Filesystem schert sich drum. Ich muß mich also mit 
meinen Structs nach den Karten richten und nicht umgekehrt.

Und jetzt tönst du
""int" sagt: "Gib mir eine Ganzzahl, mit der ich sinnvoll..."

Kann man sinnvoll mit so einer verqueren Definition arbeiten? Nee, 
natürlich nicht. Man muß leider stattdessen nachschauen, wie int, long 
usw. auf dem konkreten Ziel definiert ist und seine Quelle danach 
richten, sonst wird nix - insbesondere nix mit Zeigern. Aber damit ist 
man eben überhaupt nicht portabel, sondern tanzt auf dem Schlappseil.

soviel zu der angeblich 'sauberen' Bedeutung.

Sam P. schrieb:
> stdint.h ist integraler Bestandteil der C-Laufzeitumgebung. Es sind
> keine Pseudotypen und es findet keine Textersetzung im Präprozessor
> statt.

Ach ja? Lies mal (Auszug aus aktueller Yagarto)

typedef signed char int8_t ;
typedef unsigned char uint8_t ;

Du weißt, daß man mit typedef keine Typen definieren kann, ja?
Mit typedef kann man - salopp gesagt - einem bereits vorhandenen Typ 
einen anderen Namen geben. Eben ein Pseudotyp

Es ist 'int8_t' für den Compiler also tatsächlich nix anderes als ein 
schnöder 'signed char' - und wenn du ne inkompatible Verwendung im 
Quelltext machst, dann lautet die Fehlermeldung etwa so:
"Error 123456: cannot convert signed char to blablabla."
Da wirst du eben nicht finden "...cannot convert int8_t to blablabla".

Was ich gemeint habe wäre, daß genau SOLCHE Zeilen eben nicht mehr 
vorkommen dürften, sondern sowas wie 'int8_t' als solches vom Compiler 
verstanden wird. Als echtes Schlüsselwort mit einer Bedeutung, die für 
ALLE Maschinen gleich ist. Weil man nämlich beim Programmieren 
Probleme lösen muß und dazu Datentypen benötigt, die den Problemen 
angepaßt sind.

(über den konkreten Namen von sowas läßt sich streiten, 'byte' find ich 
deutlich besser als 'uint8_t').

Also, hast du es jetzt gerafft?

W.S.

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

W.S. schrieb:

> Als Programmierer muß man sich auf die verwendeten Datentypen verlassen
> können, was in C nicht der Fall ist.

Dann lies das ABI und die Spezifikation der Implementierung!

Beispiel: avr-gcc ABI:

http://gcc.gnu.org/wiki/avr-gcc#ABI

Da steht nämlich drinne, wie groß ein int ist, wie breit ein Zeiger, ob 
ein char signed ist oder nicht, wie Bitfelder gelayoutet sind, wie 
Funktionsparameter übergeben wwerden, etc.

Und wenn die das mit dem int nicht gefällt, nimm eben in int32_t, 
int32_fast_t oder int32_least_t.

Oder nimm Java oder Assembler wenn dir C nicht passt.

von int-Hasser (Gast)


Lesenswert?

> Dann lies das ABI und die Spezifikation der Implementierung!

Der Murks geht dann los, wenn der Code portiert werden soll. Viel Spaß 
beim umwursteln und durchsehen aller Variablen auf richtiges Format. :-(

Ich benutze schon lange kein int und co mehr. Totaler Mist.

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

int-Hasser schrieb:
>> Dann lies das ABI und die Spezifikation der Implementierung!
>
> Der Murks geht dann los, wenn der Code portiert werden soll. Viel Spaß
> beim umwursteln und durchsehen aller Variablen auf richtiges Format. :-(
>
> Ich benutze schon lange kein int und co mehr. Totaler Mist.

Ja was wollt ihr denn?

- int etc. ist euch nicht genehm
- uint32_t etc. auch nicht
- eine andere Spache auch nicht

Hauptsache Rummeckern.  Wie die Leute die stänfig übers Wetter nörgeln 
anstatt nach auszuwandern, gescheite Klamotten zu kaufen, sich 
abzuhärten oder einfach am Kamin sitzen zu bleiben wenn's Wetter nicht 
passt.

Und das niemand mehr Doku, Spezifikation, Spezifikaton der 
Implementierung, (E)ABI, etc. durchliest -- oder wenigstens nicht bei 
jeder sich bietenden Gelegenheit seine Unwissenheitsfrust rausposant -- 
ist im Zeitalter der 1-Click Mentalität wohl als gegeben hinzunehmen...

von int-Hasser (Gast)


Lesenswert?

> Ja was wollt ihr denn?

Maoam? :)

> uint32_t etc. auch nicht

doch - das ist ok. Da weiß man ja was man hat. Es geht ja grade darum, 
dass man als Programmierer etwas haben will, was eindeutig und 
unabhängig von der Bitbreite der Zielhardware definiert ist.

so kommt es dazu, dass code wie dieser hier auf einem Cortex korrekt 
funktioniert aber nicht auf einem Atmega (weil dort ein int nur 16 bit 
hat):
1
void xy(void)
2
{ int bla
3
4
bla = var_32_bit;
5
//...
6
}

Viel Spaß beim Portieren! Hätte man statt int einfach int32_t genommen 
wäre das nicht passiert und der code wäre ohne änderung portierbar 
geblieben.

von Sam P. (Gast)


Lesenswert?

W.S. schrieb:
> Du hast ne ziemlich seltsame Denkweise, die ich nicht teile.
> Als Programmierer muß man sich auf die verwendeten Datentypen verlassen
> können, was in C nicht der Fall ist.

Natürlich kann man sich auf "int" verlassen. Nämlich darauf, dass ein 
"int" relativ effizient in Berechnungen eingesetzt werden kann und dabei 
nicht unnütz klein ist. Das ist auf jedem System so, das einen 
gescheiten C-Compiler hat. Selbstverständlich kannst du dich nicht auf 
etwas verlassen, was gar nicht versprochen wird. "int" verspricht nicht, 
dass es eine feste Größe hat, aber jeder C-Neuling glaubt, das wäre so. 
Das ist das (zugegeben unglückliche) Missverständnis.

Und darum ist es gut, dass es "jetzt endlich" (seit ~15 Jahren) 
zusätzliche Typen gibt, die eben eine bestimmte Größe versprechen, dabei 
aber eventuell langsam sein könnten.


> Natürlich brauche ich auch auf
> einem 8 Bit uC 32 Bit Integerzahlen, gelegentlich auch int64, und auch
> auf der größten und dicksten Maschine ist es öfter als du denkst nötig,
> Integers bei 16 Bit "zu deckeln", wenn die Daten nämlich in Strukturen
> hineinpassen müssen, die von anderswo vorgegeben sind.

Da hast du völlig recht. Darum gibt es int16_t/int32_t/int64_t. 
short/int/long/long long sind dafür weder gedacht noch geeignet. Guck 
dir ein beliebiges C-Projekt an, das in irgendeiner Form von genauen 
Größen abhängig ist und auf wenigstens 2 Plattformen läuft (und wenn's 
nur Win32 und Win64 sind). Ist die Software nur alt genug, haben die 
Programmierer genau das gemacht, was mit stdint.h nun vereinheitlicht 
ist. Keiner, der mal etwas real portieren musste, benutzt int&Co, wenn 
die genaue Speicherbelegung relevant ist.


> Fall 1: Ich will das Ergebnis eines ADC's lesen. z.B. AD7714. Kommt bei
> Leuten, die mit Mikrocontrollern zu tun haben vor, sowas. Was kann ich
> dazu nehmen? int  oder long? Natürlich nehme ich long, weil das am
> wahrscheinlichsten die 24 Bit aufnehmen kann, die der IC ausgibt. Auf
> manchen Zielsystemen könnte ich auch int nehmen, aber wer garantiert mir
> das? Merkst du was? Wohldefinierte Datentypen sind für saubere und
> portable Programmierung wichtiger als die Befindlichkeit einer Maschine.

long? Wenn du Pech hast, hat ein long auch nur 16 Bit. "Am 
wahrscheinlichsten"? Seltsame Art zu programmieren. Jemand, der C kann, 
nimmt einen int32_t, da hast du deine klare Definition. Du willst klar 
definierte Typen, lehnst aber die klar definierten Typen ab.


> Fall 2: Ich will Daten auf eine SD-Karte schreiben und muß dazu die
> SD-Karte ansprechen, also initialisieren, die diversen Parameterblöcke
> auslesen, dann ein Filesystem aufsetzen usw. Natürlich richtet sich auch
> hier kein SD-Karten-Hersteller nach den Befindlichkeiten des verwendeten
> uC und auch kein Filesystem schert sich drum. Ich muß mich also mit
> meinen Structs nach den Karten richten und nicht umgekehrt.

Uh, structs. Ein weiteres Minenfeld. Grobe Faustregel: Bei structs hast 
du keinerlei Garantien, wo die Variablen landen. Nur die Reihenfolge 
wird eingehalten. Es gibt Architekturen (z.B. ARMv4), die können auf 
keine int32_t zugreifen, die nicht auf durch 4 teilbaren Adressen 
liegen. Auf einem solchen System muss eine
1
struct {
2
uint16_t cmd;
3
uint32_t addr;
4
}

8 Bytes lang sein, statt der 6 die man erwarten könnte. Da kann man bei 
vielen Compilern per #pragma oder _attribute_ etwas anderes erzwingen, 
aber der ARMv4 kann gar nicht anders. Und darum ist C so schwammig, weil 
eben die Hardware Vorrang vor der Bequemlichkeit des Programmierers hat.

Das ist nicht das was du hören möchtest oder von einer bequemen 
Programmiersprache erwartest, aber beim hardwarenahen Programmieren geht 
es eben nicht anders. Hätte man einen Standard verabschiedet, der alle 
Plattformen über einen Kamm schert, dann wäre das einzige Resultat, dass 
jede abweichende Plattform einen Scheiss auf den Standard gibt und 
eigene Regeln erlässt. Das Resultat wäre das gleiche wie jetzt, nur 
jetzt ist klar standardisiert, wo ein Compiler auf welche Weise 
abweichen darf, und wo nicht.


> Und jetzt tönst du
> ""int" sagt: "Gib mir eine Ganzzahl, mit der ich sinnvoll..."
>
> Kann man sinnvoll mit so einer verqueren Definition arbeiten? Nee,
> natürlich nicht. Man muß leider stattdessen nachschauen, wie int, long

Da die Definition nicht verquer ist, sondern nur etwas verspricht, was 
dir egal ist, kann ich sehr gut mit sowas arbeiten. Ich weiss, worauf 
ich mich bei einem int verlassen kann, und worauf nicht. int64_t 
verspricht mir etwas anderes, und lässt dafür die Frage nach der 
Effizienz offen.

Meine Schleifenindizes sind ints oder unsigned ints, solange ich nicht 
aufgrund besonderer Umstände mit besonders großen Zahlen rechnen muss. 
Meine Arrays sind per uintXX_t genauer spezifiziert, weil dort der 
Speicherbedarf relevant ist und man "int" da nicht vertrauen kann.


> usw. auf dem konkreten Ziel definiert ist und seine Quelle danach
> richten, sonst wird nix - insbesondere nix mit Zeigern. Aber damit ist
> man eben überhaupt nicht portabel, sondern tanzt auf dem Schlappseil.

Eben. Ich verwende ja auch keinen Schraubenzieher als Meissel. Das geht 
ne Weile gut, für einen Quick&Dirty-Job kommt man auch damit durch, aber 
irgendwann merkt man, dass ein Meissel andere Versprechen hält als ein 
Schraubenzieher.


> soviel zu der angeblich 'sauberen' Bedeutung.

Lies den C-Standard, dann weisst du wie sauber das definiert ist. Du 
kannst dir gerne ein anderes C herbeiwünschen, aber weder du noch ich 
machen die Regeln, sondern das ISO-Gremium. Und die sagen klipp und 
klar, was geht und was nicht geht.


> Sam P. schrieb:
>> stdint.h ist integraler Bestandteil der C-Laufzeitumgebung. Es sind
>> keine Pseudotypen und es findet keine Textersetzung im Präprozessor
>> statt.
>
> Ach ja? Lies mal (Auszug aus aktueller Yagarto)
>
> typedef signed char int8_t ;
> typedef unsigned char uint8_t ;
>
> Du weißt, daß man mit typedef keine Typen definieren kann, ja?
> Mit typedef kann man - salopp gesagt - einem bereits vorhandenen Typ
> einen anderen Namen geben. Eben ein Pseudotyp

Es ist aber kein Präprozessor-Makro, es basiert nicht auf Textersetzung, 
es funktioniert wie jedes andere Symbol auch. Damit hält es sich an alle 
Regeln der Sprache und ist für den Programmierer ununterscheidbar von 
einem vom Compiler vordefinierten Typ. Wie das unter der Haube 
realisiert wird, ist doch vollkommen egal.

Schreib dir halt einen Patch für deinen Compiler, der "uint8_t" intern 
definiert, sobald er die magische Zeile "#include <stdint.h>" liest. Die 
interne Datenstruktur, die du dabei anlegst, wird bis auf den Namen 
exakt die von "signed char" sein. Und nun rate mal, was bei einem 
typedef passiert. Genau das gleiche.


> Es ist 'int8_t' für den Compiler also tatsächlich nix anderes als ein
> schnöder 'signed char' - und wenn du ne inkompatible Verwendung im

Och, "char" könnte ja auch 16 Bit haben. Kein Compilerhersteller wäre so 
verwegen, aber erlaubt wäre es. Dann wäre "int8_t" irgendwas anderes als 
"char", z.B. ein interner 8-Bit-Datentyp.


> Quelltext machst, dann lautet die Fehlermeldung etwa so:
> "Error 123456: cannot convert signed char to blablabla."
> Da wirst du eben nicht finden "...cannot convert int8_t to blablabla".

Das liegt an deinem Compiler, nicht am C-Standard. Meiner ist so 
hilfreich und nennt sowohl den verwendeten Typennamen, als auch die 
zugrundeliegende Definition des Typen. Das ist sogar noch hilfreicher, 
weil ich damit zusätzliche Informationen zur impliziten Typumwandlung 
bekommen (gleich der nächste Fettnapf-Klassiker für C-Neulinge).

Ich gebe dir recht, dass Compiler-Fehlermeldungen einem das Leben schon 
schwer machen können. Ich habe z.B. C++ STL lange gehasst, wegen der 
undurchschauberen Fehlermeldungen. Aber das ist nicht die Schuld von 
C(++), sondern des Compiler-Herstellers. Wenn das der einzige haltbare 
Grund ist, ist das Jammern auf hohem Niveau.


> Was ich gemeint habe wäre, daß genau SOLCHE Zeilen eben nicht mehr
> vorkommen dürften, sondern sowas wie 'int8_t' als solches vom Compiler
> verstanden wird. Als echtes Schlüsselwort mit einer Bedeutung, die für
> ALLE Maschinen gleich ist. Weil man nämlich beim Programmieren

int8_t ist für alle Maschinen gleichbedeutend, solange wir vom 
Speicherbedarf reden. Darum gibt es diese Typen doch. Das ist genau das, 
was du die ganze Zeit herbeisehnst. Klare Ansage, auf jeder Plattform 
vorhanden, gehorcht überall den gleichen Regeln, ist nicht von anderen 
Datenypen zu unterscheiden, wo war nochmal das Problem?

Ach ja, Compiler-Fehlermeldungen. Nimm demnächst gcc-4.8, der ist so 
dermaßen ausführlich, dass da niemand mehr auch nur irgendwas 
missverstehen kann. Der zeigt dir sogar die Quelltext-Zeile mit der 
genauen Position des Fehlers. Da wo dann "int8_t" steht. Ich hoffe das 
reicht dir. Wird wohl nicht mehr lange dauern, bis der 4.8er offiziell 
herausgegeben wird. Die Prereleases funktionieren schon ganz gut.


> Probleme lösen muß und dazu Datentypen benötigt, die den Problemen
> angepaßt sind.

Lautet dein Problem "Messwerte mit Zahlenwerten zwischen 0 und 3 
Millarden speichern", dann nimm einen uint32_t pro Messwert.

Lautet dein Problem "So viele Messwerte, wie ins RAM passen, in einer 
Schleife erfassen und abspeichern", dann ist "unsigned int" die einzige 
sinnvolle Wahl für den Schleifenzähler/Array-Index. uint16_t wäre auf 
einer 32-Bit-Architektur zu klein, uint32_t wäre auf einem 8-Bitter zu 
langsam.


> Also, hast du es jetzt gerafft?

Offensichtlich nicht. Es gibt das was du dir wünschst, wenn auch mit 
Namen, die deiner Ästhetik nicht ganz entsprechen. Es ist offiziell, es 
ist überall verfügbar, überall gleich definiert und voll in die Sprache 
integriert. Willst du jetzt allen Ernstes über Compiler-Fehlermeldungen 
schmollen, wo ohenhin jeder Compiler-Hersteller tun und lassen kann was 
er will, und deswegen so eine sinnvolle Einrichtung ablehnen?




Rolf Magnus schrieb:
> Sam P. schrieb:
>> Einerkomplement ist genauso erlaubt wie Zahl+Vorzeichenbit. Das macht
>> natürlich keiner, weil praktisch jedes nichttriviale C-Programm dann
>> nicht mehr funktioniert, aber erlaubt wäre es.
>
> Warum sollten Programme dann nicht mehr funktionieren?

Sehr viel Code macht Annahmen über die konkreten Bitmuster, die einer 
bestimmten Zahl entsprechen. Heutzutage gibt es bei Integern den 
Quasi-Standard "Zweierkomplement", der auch viel Sinn macht. Aber 
nirgendwo steht geschrieben, dass das in C unbedingt so sein muss. "~0" 
kann entweder "-1" oder "-0" sein. "-0" alleine ist schon kurios (gibts 
bei Fliesskomma immer noch). "(-1) << 1" ist -2, -3 oder +2, je nachdem 
ob man Zweierkomplement, Einerkomplement oder "positive Zahl plus 
Vorzeichenbit" hat. -127 - 1 als int8_t kann -128, +127 oder +0 sein. 
Darum ist Überlauf bei vorzeichenbehafteten Zahlen in C auch offiziell 
undefiniert.

Das ändert aber nichts an der Realität, dass ganz oft damit gearbeitet 
wird. Gerade die Shift-Operatoren werden gerne als angeblich effiziente 
Multiplikation/Division verwendet, wo doch jeder Compiler der letzten 10 
Jahre ein "* 4" automatisch zu einem "<< 2" umschreibt, dabei aber die 
Zahlenformate korrekt berücksichtigt. Für ein ganz perverses Beispiel 
von Bitmuster-Hacking google mal nach 0x5f3759df.



Nu is aber gut, das ist ja furchtbar lang. Ich hoffe, die 
Ausführlichkeit hat wenigstens zu etwas Erkenntnisgewinn beigetragen.

von runni (Gast)


Lesenswert?

U8 S8 U16.... ist bei Silabs sehr gebräuchlich und keines wegs schlecht 
zu verstehen, habe das auch schon bei anderen gesehen... glaube auch bei 
peda :-)

von (prx) A. K. (prx)


Lesenswert?

Sam P. schrieb:
> long? Wenn du Pech hast, hat ein long auch nur 16 Bit.

Nein. Muss mindestens 32 Bits haben.

> Meine Schleifenindizes sind ints oder unsigned ints, solange ich nicht
> aufgrund besonderer Umstände mit besonders großen Zahlen rechnen muss.

Yep. Konsequente Verwendung von [u]intNN_t mit NN <= 16 kann zu recht 
ineffizientem Code führen, da mangels entsprechender Operationen bei 
RISCs wie ARM immer wieder das Resultat auf NN Bits reduziert werden 
muss.

Offiziell sind dafür deshalb die Typen [u]int_fastNN_t vorgesehen, aber 
an Stelle von [u]int_fast16_t kann man für lokale Variablen de fakto 
ebenso gut [unsigned]int verwenden.

> Och, "char" könnte ja auch 16 Bit haben. Kein Compilerhersteller wäre so
> verwegen, aber erlaubt wäre es. Dann wäre "int8_t" irgendwas anderes als
> "char", z.B. ein interner 8-Bit-Datentyp.

In diesem Fall würde int8_t wahrscheinlich nicht geben. Diesen Typ gibt 
es nur, wenn ein Typ mit exakt 8 Bits überhaupt existiert.

von nicht "Gast" (Gast)


Lesenswert?

Peter II schrieb:
> im gcc ist es immer signed
> #include <stdio.h>
> int main() {
>   char c = 0xff;
>   int i = c;
>   printf("test:%d\n", i );
>
> na was kommt raus?


Moin, das heißt nur, das du von C programmieren keine Ahnung hast. Wenn 
du dem natürlich sagst, dass er es als signed interpretieren soll... 
versuch mal den Umkehrschluss mit printf("test:%u\n", i ); und int. Das 
wird dich überraschen.


Ich weiß, das ist Uhralt, aber mich hats grad in den Fingern gejukt^^

Grüße,

von Coder (Gast)


Lesenswert?

Nette Diskussion. Wenn jemand int benutzen möchte, soll er das. Man 
sollte niemanden zu seinem Glück zwingen.

von Fabian O. (xfr)


Lesenswert?

@ Sam P.: Super Beitrag. Damit ist wohl so ziemlich alles abgedeckt, was 
man zu dem Thema sagen kann. :)

A. K. schrieb:
> Yep. Konsequente Verwendung von [u]intNN_t mit NN <= 16 kann zu recht
> ineffizientem Code führen, da mangels entsprechender Operationen bei
> RISCs wie ARM immer wieder das Resultat auf NN Bits reduziert werden
> muss.
>
> Offiziell sind dafür deshalb die Typen [u]int_fastNN_t vorgesehen, aber
> an Stelle von [u]int_fast16_t kann man für lokale Variablen de fakto
> ebenso gut [unsigned]int verwenden.

Auf 8-Bit-Mikrocontrollern reichen für viele Dinge wie Schleifen und 
Statusvariablen allerdings auch schon 8 Bit. In solchen Fällen ist man 
mit uint_fast8_t am besten bedient. Dafür gibt es keine Entsprechung in 
den nativen Typen.

Ich bin allerdings auch nicht besonders konsequent bei der Verwendung, 
wenn ich nicht schon weiß, dass der Code auf mehreren Plattformen laufen 
muss. Werde dank des Threads da mal wieder genauer drauf achten ... :)

von C-Gast (Gast)


Lesenswert?

Hallo,
habt Ihr bitte einen guten Artikel, aus dem die richtige und sinnvolle 
Verwendung der verschiedenen Datentypen hervorgeht?
Von "uint_fast8_t" hatte ich bis dato leidr noch nicht mal was gehört... 
aber man lernt ja gerne dazu
Danke

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

A. K. schrieb:

>> Meine Schleifenindizes sind ints oder unsigned ints, solange ich nicht
>> aufgrund besonderer Umstände mit besonders großen Zahlen rechnen muss.
>
> Yep. Konsequente Verwendung von [u]intNN_t mit NN <= 16 kann zu recht
> ineffizientem Code führen, da mangels entsprechender Operationen bei
> RISCs wie ARM immer wieder das Resultat auf NN Bits reduziert werden
> muss.

Das sieht man besonders häufig bei Code, der aus der 16-Bit Ära überlebt 
hat — und das ist eher die Regel als die Ausnahme, etwa bei den 
Automotives.  Der Code ist dann gepflastert mit hausbackenen NIH-Typen* 
wie U16, S16, WORD, sint16 oder uint16.  Und selbst [u]int16_t ist da 
voll exotisch.

Auf einem 32-Bit µC bremst knabbert das natürlich merklich an der 
Performance: Der Code wird langsamer und größer.

> Offiziell sind dafür deshalb die Typen [u]int_fastNN_t vorgesehen, aber
> an Stelle von [u]int_fast16_t kann man für lokale Variablen de fakto
> ebenso gut [unsigned]int verwenden.

Die sind mir in freier Wildbahn allerdings noch nie begegnet, was 
mehrere Gründe haben mag: Mangelndes Wissen der Anwender, Paranoide 
Coding-Rules, NIH-Attitüden, oder es liegt schlicht und ergreifend kein 
C99 vor wegen M$-Compiler etc.



*) NIH = "Not invented here".  Alles was nicht auf unserem Mist 
gewachsen ist, ist Schrott.

von Rolf M. (rmagnus)


Lesenswert?

W.S. schrieb:
> Du hast ne ziemlich seltsame Denkweise, die ich nicht teile.

Die ist nicht seltsam.

> Mir ist ein bissel rätselhaft, wie du zu deinen Auffassungen kommst,
> deswegen hier ein paar Beispiele, damit du merkst, worum es geht:
>
> Fall 1: Ich will das Ergebnis eines ADC's lesen.

> Fall 2: Ich will Daten auf eine SD-Karte schreiben und muß dazu die
> SD-Karte ansprechen, also initialisieren, die diversen Parameterblöcke
> auslesen, dann ein Filesystem aufsetzen usw.

Beides Lowlevel-Interfaces nach außen. Für die braucht man natürlich 
einen passenden Typen. Aber der muß nicht nur die richtige Größe haben, 
sondern auch die richtige Byteorder und andere Dinge. Willst du die dem 
Compiler auch global vorschreiben, auch wenn die auf dem Zielsystem 
höllisch langsam sind, nur damit man beim Ansprechen einer SD-Karte 
nicht nachdenken muß? Der Löwenanteil des C-Codes, der auf einem System 
läuft besteht in der Regel nicht aus lowlevel-Interfaces. Und dort sind 
effiziente Typen wichtiger als welche, die sich an starre Vorgaben von 
außen halten, insbesondere, wenn diese Vorgaben bei mehreren Interfaces 
auch noch unterschiedlich sein können.

> Kann man sinnvoll mit so einer verqueren Definition arbeiten?

Ja. Konnte ich bisher zumindest immer.

> Es ist 'int8_t' für den Compiler also tatsächlich nix anderes als ein
> schnöder 'signed char' - und wenn du ne inkompatible Verwendung im
> Quelltext machst, dann lautet die Fehlermeldung etwa so:
> "Error 123456: cannot convert signed char to blablabla."
> Da wirst du eben nicht finden "...cannot convert int8_t to blablabla".

Ach ja? Bei
1
#include <stdint.h>
2
#include <stdio.h>
3
int main()
4
{
5
    struct {} s;
6
    int8_t i;
7
    s = i;
8
    scanf("%f\n", &i);
9
}

spuckt mein gcc aus:
1
uint.c:7:7: Fehler: unverträgliche Typen bei Zuweisung an Typ »struct <anonym>« von Typ »int8_t«
2
uint.c:8:5: Warnung: Format »%f« erwartet Argumenttyp »float *«, aber Argument 2 hat Typ »int8_t *« [-Wformat]

Die Sache ist also eher ein Problem der Qualität des Compilers, denn es 
ist diesem nicht verboten, bei Warnungen den typedef-Namen auszugeben 
statt des Namens, auf den der typedef verweist.

> Was ich gemeint habe wäre, daß genau SOLCHE Zeilen eben nicht mehr
> vorkommen dürften, sondern sowas wie 'int8_t' als solches vom Compiler
> verstanden wird. Als echtes Schlüsselwort mit einer Bedeutung, die für
> ALLE Maschinen gleich ist.

Sie ist für alle Maschinen gleich. Es ist halt ein typedef, statt eines 
Schlüsselwortes. Einen Nachteil kann ich dabei nicht erkennen.

von (prx) A. K. (prx)


Lesenswert?

Nebenbei: Der Unterschied zwischen Schlüsselworten und Typedefs ist 
syntaktisch betrachtet nicht sonderlich gross. Typedefs wurden erst 
nachträglich in C eingeführt, allerdings schon zu K&R Zeiten, und passen 
eigentlich nicht in eine Syntax, in der Deklarationen durch ein 
einleitendes Typ-Schlüsselwort wie "int" erkannt werden. Das gibt 
Typedef-Namen eine Sonderrolle, da sie keine einfachen Identifier sein 
können.

Folglich wird ein Compiler mit schematischem Parser wie Bison bereits in 
der lexikalischen Analyse einen Identifier danach untersuchen, ob es ein 
Typedef-Name oder ein anderer Name ist, und ein entsprechendes anderes 
Token an den Parser reichen. Eingeschränkt dadurch, dass der Name an 
einigen wenigen Stellen wieder ein normaler Name ist, beispielsweise 
direkt hinter enum/struct/union, was Lexer und Parser enger koppelt, als 
Reitern von Sprachprinzipien lieb ist.

von Fabian O. (xfr)


Lesenswert?

C-Gast schrieb:
> Hallo,
> habt Ihr bitte einen guten Artikel, aus dem die richtige und sinnvolle
> Verwendung der verschiedenen Datentypen hervorgeht?
> Von "uint_fast8_t" hatte ich bis dato leidr noch nicht mal was gehört...
> aber man lernt ja gerne dazu
> Danke

Du musst Dir im Prinzip einfach drei Fragen beantworten:


1. Können die zu speichernden Werte negativ sein?

Wenn nein, nimmt man einen vorzeichenlosen Typ (unsigned, uintXX_t). 
Wenn ja, einen vorzeichenbehafteten (signed, intXX_t).


2. Wie groß können die Werte maximal werden?

Davon hängt die erforderliche Breite des Typs in Bit ab.
1
Breite |      unsigned       |             signed            
2
       | min |           max |            min |           max
3
8  Bit |   0 |           255 |           -128 |           127
4
16 Bit |   0 |        65.535 |        -32.768 |        32.767
5
32 Bit |   0 | 4.294.967.295 | -2.147.483.648 | 2.147.483.647
6
64 Bit |   0 |      2^64 - 1 |          -2^63 |      2^63 - 1


3. Muss der Datentyp auf jeder Plattform gleich groß sein?

Wenn ja, dann nimmt man uint8_t, int16_t etc. Damit weiß man genau, wie 
viele Bytes die Daten im Speicher belegen. Das ist inbesondere bei 
Datenstrukturen wichtig, die man mit anderen Komponenten austauscht.

In den meisten anderen Fällen genügt es aber, wenn man weiß, dass der 
Typ mindestens den erforderlichen Wertebereich abdeckt. Es macht aber 
nichts, wenn man auch größere Zahlen darin speichern könnte. Das gilt 
besonders für lokale Variablen für Berechnungen, Schleifenzähler, 
Statusvariablen usw.. Dafür gibt es die Typen (u)int_leastXX_t und 
(u)int_fastXX_t. Die garantieren, dass sie mindestens XX Bit breit sind, 
können aber auch größer sein.

Der Typ int_fastXX_t hat den Hintergrund, dass es auf 
32/64-Bit-Prozessoren in der Regel aufwändiger ist, mit nur 8 oder 16 
statt den vollen 32/64 Bit des Registers zu rechnen, da die oberen Bits 
immer noch extra ausmaskiert werden müssen. Bei so einer Plattform 
bremst man das Programm also unnötig aus, wenn man auf kleinere 
Bitbreiten für die Berechnungen besteht. Mit int_fastXX_t erhält man 
immer den Typ, der sich am effizientesten verarbeiten lässt, aber 
mindestens XX Bits aufnimmt. Ein int_fast8_t wird auf einem 
32-Bit-Prozessor also höchstwahrscheinlich 32 Bit breit sein, auf einem 
8-Bit-Mikrocontroller dagegen nur 8 Bit.

Die int_leastXX_t sind dagegen afaik eher akademischer Natur. Sie bieten 
mindestens XX Bit und sind der kleinstmögliche Typ, der mit dieser 
Breite zur Verfügung steht. In aller Regel dürften sie daher genau XX 
Bit breit sein, sofern die Plattform nicht über eine ganz exotische 
Speicherorganisation verfügt. Bitte korrigieren, falls ich da falsch 
liege ...

So, und dann gibt es noch die traditionellen C-Datentypen:
               Breite
char           mind.  8 Bit
short int      mind. 16 Bit
int            mind. 16 Bit
long int       mind. 32 Bit
long long int  mind. 64 Bit

Jeder davon ist auch unsigned möglich.

Der einfache int entspricht normalerweise entweder dem short int oder 
long int, jenachdem, was auf der Plattform effizienter zu rechnen ist. 
Damit ist ein int praktisch äquivalent zu einem int_fast16_t. Für 
int_fast8_t gibt es dagegen keine Entsprechung. Auf einem 
Mikrocontroller müsste man (signed) char benutzen, auf größeren 
Plattformen dagegen int.

von (prx) A. K. (prx)


Lesenswert?

Fabian O. schrieb:
> Die int_leastXX_t sind dagegen afaik eher akademischer Natur.

Sie sind dort relevant, wo ein exakter Typ nicht vorliegt. Mangels 
entsprechender Maschinenoperationen hatte ich bei einem Compiler für 
Transputer in der 32-Bit Fassung keinen 16-Bit Datentyp implementiert. 
int16_t wird in einem solchen Fall nicht existieren, int_least16_t 
hingegen schon.

von (prx) A. K. (prx)


Lesenswert?

Fabian O. schrieb:
> Der einfache int entspricht normalerweise entweder dem short int oder
> long int, jenachdem, was auf der Plattform effizienter zu rechnen ist.

Nein. Das in Linux übliche 64-Bit Programmiermodell LP64 verwendet 64 
Bits für "long", 32 Bits für "int" und 16 Bits für "short". Nur in der 
Windows-Variante LLP64 muss für 64 Bits auf "long long" ausgewichen 
werden.

von Fabian O. (xfr)


Lesenswert?

A. K. schrieb:
> Sie sind dort relevant, wo ein exakter Typ nicht vorliegt.

Dorgh, ich muss aus Versehen auf Absenden statt Vorschau geklickt haben. 
Beim Durchlesen ist es mir nämlich auch aufgefallen. Beim Absenden kam 
dann die Meldung, ich dürfte nich mehr editieren ...

Hier die richtige Fassung:

Die int_leastXX_t sind dagegen afaik eher ungebräuchlich. Sie bieten 
mindestens XX Bit und sind der kleinstmögliche Typ, der mit dieser 
Breite zur Verfügung steht. In der Regel sind sie also genau XX Bit 
breit. Nur falls die Plattform keine kleineren Typen addressieren kann, 
sind sie größer. Das ist beispielsweise bei manchen DSPs der Fall, bei 
denen ein char dann 16 Bit breit ist. Man kann die int_leastXX_t also 
nutzen, wenn einem wichtig ist, dass möglichst wenig RAM gebraucht wird, 
der Code aber auch auf Plattformen läuft, auf denen es z.B. kein int8_t 
gibt.

von Fabian O. (xfr)


Lesenswert?

A. K. schrieb:
> Fabian O. schrieb:
>> Der einfache int entspricht normalerweise entweder dem short int oder
>> long int, jenachdem, was auf der Plattform effizienter zu rechnen ist.
>
> Nein. Das in Linux übliche 64-Bit Programmiermodell LP64 verwendet 64
> Bits für "long", 32 Bits für "int" und 16 Bits für "short". Nur in der
> Windows-Variante LLP64 muss für 64 Bits auf "long long" ausgewichen
> werden.

OK, wieder was gelernt. Habe mir schon fast gedacht, dass es da 
Ausnahmen von gibt, daher "normalerweise" ... Dass das bei Linux 
Standard ist, war mir aber nicht bewusst. :)

von (prx) A. K. (prx)


Lesenswert?

Könnte sich lohnen, wenn du einen Artikel draus machst.

von (prx) A. K. (prx)


Lesenswert?

Fabian O. schrieb:
> Davon hängt die erforderliche Breite des Typs in Bit ab.
> 8  Bit |   0 |           255 |           -128 |           127

Der Vollständigkeit halber: Der Standard garantiert nur -127..+127. 
Grössere Typen analog. Ist aber eine eher exotische Einschränkung.

von Fabian O. (xfr)


Lesenswert?

A. K. schrieb:
> Könnte sich lohnen, wenn du einen Artikel draus machst.

Stimmt schon, hier im Thread findet man es schlecht wieder. Ich habe mal 
einen Artikel erstellt, werde ihn in den nächsten Tagen noch erweitern. 
Wenn eh grad der Wettbewerb läuft ... :)

http://www.mikrocontroller.net/articles/Plattformunabh%C3%A4ngigkeit

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

Fabian O. schrieb:
> A. K. schrieb:
>> Könnte sich lohnen, wenn du einen Artikel draus machst.
>
> Stimmt schon, hier im Thread findet man es schlecht wieder. Ich habe mal
> einen Artikel erstellt, werde ihn in den nächsten Tagen noch erweitern.
> Wenn eh grad der Wettbewerb läuft ... :)
>
> Plattformunabhängigkeit

Diskussion:Plattformunabhängigkeit: Was noch fehlt

von W.S. (Gast)


Lesenswert?

Sam P. schrieb:
>> Also, hast du es jetzt gerafft?
>
> Offensichtlich nicht. Es gibt das was du dir wünschst, wenn auch mit
> Namen, die deiner Ästhetik nicht ganz entsprechen. Es ist offiziell, es
> ist überall verfügbar, überall gleich definiert und voll in die Sprache
> integriert...

Es ist ein Manko, ein Geburtsfehler der Sprache C - und keiner hat es 
bisher geschafft, damit mal wirklich aufzuräumen. Leider. Immer nur ein 
Workaround auf den anderen. Wer in C programmiert, muß damit irgendwie 
zurechtkommen. Wie auch immer.

Die Ästhetik finde ich Mist. Aber da all diese Pseudotypen ja ohnehin 
nicht zum Sprachumfang gehören, kann sich jeder nach eigenem Gusto U8, 
W16, N24, uint16_t und noch viele weitere Hausausdrücke einfallen 
lassen. Babylon ist überall.

Aber mal zum Kern der Sache:
Es (s.o.) ist weder voll noch irgendwie in die Sprache integriert, 
sondern völlig unintegriert als Hilfs-Headerdatei vorliegend.

Wäre "ES" integriert, dann würde man die von dir genannte Headerdatei 
überhaupt nicht benötigen, weil es die betreffenden Schlüsselwörter in 
der Sprachdefinition gäbe.

Aber es ist nicht integriert und man benötigt diese 
compilerherstellerabhängige Headerdatei, um das Konstrukt (u)int(n)_t in 
eine dem Compiler verständliche Folge von Schlüsselwörtern 
zurückzuübersetzen. Das war und ist es, was ich dir klarmachen will.

So.

Man kann mit all dem zurechtkommen. Irgendwie. Du, ich und all die 
anderen.

Aber man sollte es beim Namen nennen. Mist ist Mist - und es ist eben 
kein Gold bloß weil man es selber nicht ändern kann. Ich zumindest 
versuche nicht, mir die Dinge schönzureden.

Und nun zurück zur Ausgangsfrage:

Torsten B. schrieb:
> Weil es in der " stdint.h" so definiert ist ! Ja!
> Aber warum weicht diese vom C-Standard ab ?

Antwort: Weil die entscheidenden Gremien es nicht geschafft haben, die 
Sprache C wirklich zu modernisieren und sie stattdessen Workarounds (im 
Klartext "Hilfskrücken") wie stdint.h sich ausgedacht haben. Dort darf 
dann jeder, der sich berufen fühlt, diese Pseudotypen in geeigneter Form 
auf das herunterbrechen, was sein Compiler denn so tatsächlich versteht.

W.S.

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

W.S. schrieb:

> Die Ästhetik finde ich Mist. Aber da all diese Pseudotypen ja ohnehin
> nicht zum Sprachumfang gehören, ...

Doch tun sie. Es ist C99. Sie gehören also seit weit über 10 Jahren zum 
Standard.  Wenn dir das zu wenig ist, kann die niemand helfen.

Es ist auch nicht unüblich, Sprachen zu erweitern: Python, Java, 
Fortran, Ada, um nur ein paar wenige zu nennen.

Aber dass es dor nicht darum geht, sondern ums Nörgeln, ist inzwischen 
mehr als klar und jeder hat es verstanden.

von EGS_TI (Gast)


Lesenswert?

C-Gast schrieb:
> Hallo,
> habt Ihr bitte einen guten Artikel, aus dem die richtige und sinnvolle
> Verwendung der verschiedenen Datentypen hervorgeht?
> Von "uint_fast8_t" hatte ich bis dato leidr noch nicht mal was gehört...
> aber man lernt ja gerne dazu
> Danke

http://stackoverflow.com/questions/1953796/performance-benefit-when-using-uint-fast8-t

von Andreas B. (andreas_b77)


Lesenswert?

W.S. schrieb:
> Aber mal zum Kern der Sache:
> Es (s.o.) ist weder voll noch irgendwie in die Sprache integriert,
> sondern völlig unintegriert als Hilfs-Headerdatei vorliegend.
>
> Wäre "ES" integriert, dann würde man die von dir genannte Headerdatei
> überhaupt nicht benötigen, weil es die betreffenden Schlüsselwörter in
> der Sprachdefinition gäbe.

Hätte man es direkt integriert (das wäre trivial gewesen), wäre der neue 
Standard inkompatibel zum alten. Es gäbe neue Schlüsselwörter und bisher 
gültige Programme ließen sich mit aktualisierten Compilern unter 
Umständen nicht mehr übersetzen.

Dadurch, dass für die neuen Typen in C99 explizit ein #include 
<stdint.h> (und für die booleans ein #include <stdbool.h>) gemacht 
werden muss, haben die neu definierten Typen keinen Einfluss auf ältere 
Programme.

Und natürlich stehen die Typen in der Sprachdefinition, woher kämen wohl 
sonst die Namen stdint.h und stdbool.h?

von Yalu X. (yalu) (Moderator)


Lesenswert?

W.S. schrieb:
> Es ist ein Manko, ein Geburtsfehler der Sprache C - und keiner hat es
> bisher geschafft, damit mal wirklich aufzuräumen. Leider. Immer nur ein
> Workaround auf den anderen.

Es gibt zwei wesentliche Kriterien bei der Erweiterung von
Programmiersprachen:

  1. sauber und ästhetisch

  2. abwärtskompatibel

Da diese Kriterien teilweise im Widerspruch zueinander stehen, wird
einem von beiden eine höhere Priorität eingeräumt. Ein Beispiel für (1)
ist Python, wo immer wieder einmal aufgeräumt wird, um die Sprache als
Ganzes möglichst rund und aus einem Guß dastehen zu haben. Bei C
hingegen steht ganz klar (2) im Vordergrund, weil von vielen Firmen
C-Code über Jahrzehnte hinweg wiederverwendet wird.

Wird (1) priorisiert, meckern die Leute, dass ihre alten Programme nicht
mehr laufen. Wird hingegen (2) priorisiert, meckern die Leute, dass die
Sprache ihre klinische Reinheit verliert. Wer nur in einem der beiden
Fälle meckert, wählt einfach eine andere Programmiersprache. Wer in
beiden Fällen meckert, der sollte mit dem Programmieren aufhören :)

> Wäre "ES" integriert, dann würde man die von dir genannte Headerdatei
> überhaupt nicht benötigen, weil es die betreffenden Schlüsselwörter in
> der Sprachdefinition gäbe.

Eine gute Integration von Datentypen bedeutet nicht, dass für sie
Schlüsselwörter reserviert werden. Ich empfinde es sogar eher als
unästhetisch, wenn Datentypen, Systemvariablen, Standardfunktionen u.ä.
als Schlüsselwörter definiert werden, denn für mich ist kein Grund
ersichtlich, warum der Name eines vordefinierten Datentyps ein
Schlüsselwort sein soll, der Name eines benutzerdefinierten Datentyps
aber nicht. Konsequenterweise ist in vielen modernen Programmiersprachen
kein einziger Datentyp als Schlüsselwort definiert¹.

> Aber es ist nicht integriert und man benötigt diese
> compilerherstellerabhängige Headerdatei

Ja, und das Tolle an der Sache ist, dass man dieser Headerdatei auch
einfach weglassen kann, wenn sich die darin enthaltenen Typdeklarationen
mit bestehendem Programmcode beißen.

> Aber man sollte es beim Namen nennen. Mist ist Mist - und es ist eben
> kein Gold bloß weil man es selber nicht ändern kann. Ich zumindest
> versuche nicht, mir die Dinge schönzureden.

Aber noch viel größerer Mist (wenn auch anderer Art) wäre es, wenn eine
Softwarefirma bei jedem neuen C-Standard ihren kompletten Code-Bestand
anpassen müsste.

Ich verstehe auch nicht ganz, warum du immer wieder auf diesen stdint-
Typen herumreitest. Du kannst in den meisten Fällen auch ganz gut ohne
sie leben: Der C-Standard gibt für alle "normalen" Integertypen (also
char, short, int, long und long long, jeweils signed und unsigned) einen
minimalen Wertebereich an. Du wählst also einfach immer denjenigen Typ
aus, dessen garantierter Wertebereich für deine Berechnungen ausreichend
ist. Wie groß der (implementierungsabhängige) tatsächliche Wertebereich
ist, ist meist relativ uninteressant.

Mir fallen spontan nur zwei Fälle ein, wo die tatsächliche Bitgröße der
Integer-Typen von Bedeutung ist:

  1. wenn beim Speicherverbrauch des Programms jedes einzelne Byte zählt

  2. wenn man aus Effizienzgründen mit überlaufenden Variablenwerten als
     Ersatz für die Modulo-2^n-Arithmetik herumtricksen möchte

Aber diese Fälle treten doch eher selten auf.


–––––––––––––
¹) Manchmal wird beim Unit-Typ eine Ausnahme gemacht, was der Ästhetik
   auf Grund der Sonderrolle dieses Typs aber keinen Abbruch tut.

von Rolf M. (rmagnus)


Lesenswert?

W.S. schrieb:
> Aber mal zum Kern der Sache:
> Es (s.o.) ist weder voll noch irgendwie in die Sprache integriert,
> sondern völlig unintegriert als Hilfs-Headerdatei vorliegend.

Wir haben unterschiedliche Ansichten darüber, was zur Sprache gehört und 
was "völlig unintegriert ist". Für mich ist alles, was in der 
Sprachdefinition steht, Teil der Sprache. Das ist bei stdint.h und den 
[u]int*-Typen der Fall, also gehören sie zur Sprache.
Bei C war es schon immer so, daß man versucht hat, den - nennen wir es 
mal Sprachkern - möglichst klein zu halten und alles, was da nicht 
unbedingt drin sein muß, in die Standardbibliothek zu stecken. So gibt's 
z.B. auch die Möglichkeit zur Textausgabe (printf) nur in der Bibliothek 
und nicht, wie bei manchen anderen Sprachen, als Schlüsselwort. Stört 
dich auch, daß du dafür einen Header einbinden mußt und daß es "weder 
voll noch irgendwie in die Sprache integriert" ist? Ist printf deshalb 
kein Teil von C?

Du hast es immer noch nicht geschafft, auch nur einen einzigen Vorteil 
zu nennen, diese [u]int*-Typen als Schlüselwort statt per Header zu 
definieren.

von W.S. (Gast)


Lesenswert?

Rolf Magnus schrieb:
> Ist printf deshalb
> kein Teil von C?

Richtig. 'printf' ist genauso wie alles was in separaten Headerdateien 
steht eben kein Bestandteil der Sprache. Da zählt nur genau das, was als 
Schlüsselwort definiert ist und nichts, was in irgendwelchen 
Headerdateien steht. Das sind alles nur Workarounds, wenn es um 
Datentypen geht. Auch die ganzen Funktionen der diversen 
Standardbibliotheken gehören nicht zu den Bestandteilen der Sprache, 
sondern sind lediglich "üblicherweise vorhandene Funktionen".

'printf' kann, muß aber nicht in den Libraries einer Toolchain enthalten 
sein. Nur so als Beispiel.

Andreas B. schrieb:
> Hätte man es direkt integriert (das wäre trivial gewesen), wäre der neue
> Standard inkompatibel zum alten. Es gäbe neue Schlüsselwörter...

Ja. Eben, siehe "Int64" als Beispiel.
Es wäre ganz gewiß kein Beinbruch gewesen, 'int' als 16 Bit Zahl und 
'long' als 32 Bit Zahl festzuschreiben. Das wäre überhaupt nicht 
inkompatibel zum Bisherigen gewesen - und ich möchte hier nur mal dran 
erinnern, daß der Schritt von K&R zu ANSI ein viel größerer Schnitt in 
der Syntax gewesen ist.

Es geht - man muß bloß wollen. Und man hätte es wollen sollen. Das wäre 
was wirklich Gutes gewesen.

Nochmal im Klartext: das Festschreiben eines 'int' auf exakt 16 Bit 
und 'long' auf exakt 32 Bit wäre absolut  KEINE Inkompatibilität zu 
bisherigen Programmen gewesen - bis auf solche, bei denen die Autoren 
sich ohnehin an nix gehalten haben.

Ich halte es auch nicht für verwerflich, neue Schlüsselwörter 
einzuführen, wenn das mit der gebührenden Zurückhaltung erfolgt. Dazu 
unser Mod:

Yalu X. schrieb:
> Ich empfinde es sogar eher als
> unästhetisch, wenn Datentypen, Systemvariablen, Standardfunktionen u.ä.
> als Schlüsselwörter definiert werden

Genau DAS ist wieder mal die Übertreibung - hier mal deinerseits.

Systemvariablen und Standardfunktionen gehören nicht zu einer 
Sprachdefinition und sollen deshalb eben nicht eigene Schlüsselworte 
erhalten. Aber grundlegende Datentypen gehören zu den echten Grundlagen 
einer jeden Programmiersprache und damit in den eigentlichen 
Sprachumfang mit eigenem Schlüsselwort.

Und da gibt es in C eben nix anderes als char, int und long nebst ihren 
unsigned Versionen. Alles Andere ist in C nicht definiert.

Warum in aller Welt wollen die hier versammelten Diskutierer das nicht 
einsehen und einfach mal sagen "ja, so isses eben."

Yalu X. schrieb:
> Ich verstehe auch nicht ganz, warum du immer wieder auf diesen stdint-
> Typen herumreitest.

Um der Klarheit willen. Das isses. Klarheit.

Mit dem Gegebenen leben kann ich schon seit Jahren, ich hab in der 
Praxis damit keine Probleme bis auf solche Fälle, wo ich mich mal wieder 
durch unleserliche Fremdquellen durchackern muß. Aber ich akzeptiere 
Krummheiten eben nicht derart, daß ich mich selber krumm mache, bloß um 
sie als 'Geradheiten' ansehen zu können.

Klaro?

W.S.

von (prx) A. K. (prx)


Lesenswert?

W.S. schrieb:
> daß der Schritt von K&R zu ANSI ein viel größerer Schnitt in
> der Syntax gewesen ist.

Es war eine Erweiterung und eine klarere Spezifikation, aber kein 
Schnitt. Alte Programme blieben übersetzbar, es sei denn sie hatten das 
Pech und verwendeten die neuen Keywords - aber sowas ist trivial zu 
fixen.

Einzig jene Programme, die bei der impliziten Typkonvertierung auf 
Bewahrung der Vorzeicheneigenschaft (sign preservation) an Stelle des 
Wertes (value preservation) gesetzt hatten, die bissen ins Gras. Denn 
das findest du nicht so leicht im Code. Aber das war vorher schlicht 
nicht festgelegt. Ich hatte im Compiler deshalb vorsorglich beides 
ermöglicht.

> Nochmal im Klartext: das Festschreiben eines 'int' auf exakt 16 Bit
> und 'long' auf exakt 32 Bit wäre absolut  KEINE Inkompatibilität zu
> bisherigen Programmen gewesen

Bereits K&R erwähnt Implementierungen mit 32-Bit int (IBM 370, Interdata 
8/32) und 36-Bit short+int (Honeywell 6000).

Anno ANSI-C 1989 waren bereits viele C Compiler mit 32-Bit int im 
Einsatz.

> - bis auf solche, bei denen die Autoren
> sich ohnehin an nix gehalten haben.

Anno K&R gab es keine klare Definition des Wertebereichs von Datentypen, 
also auch nichts wogegen man hätte verstossen können. Dafür aber gab es 
viele Programme, die faktisch von sizeof(int) == sizeof(char *) 
ausgingen. Schon weil das in vielen Fällen der einzige wachsweichen 
Spezifikation entsprach, dass "int" der natürlichen Wortbreite 
entspräche. Diese einzige Regel hätte int=16bit definitiv verletzt, das 
kam also ohnehin nicht in Frage.

Natürlich kann man sich auf "zum Teufel mit denen, die nicht meiner 
Ansicht sind" verlegen, aber weit kommt man mit diesem Ansatz aufgrund 
der normativen Kraft des Faktischen nicht. Man hatte auf diesem Weg 
einen Seitenzweig eröffnet.

Mit dem Ansatz "vor mir die Sintflut" hätte man besser dran getan, die 
miserable Deklarationssystax von C gleich ganz über Bord zu werfen und 
durch eine saubere zu ersetzen. Und ein paar andere Stellen gleich mit.

> Ich halte es auch nicht für verwerflich, neue Schlüsselwörter
> einzuführen, wenn das mit der gebührenden Zurückhaltung erfolgt.

Es war ein fundamentaler syntaktischer Fehler von C, Datentypen 
überhaupt erst zu Keywords zu machen.

> Systemvariablen und Standardfunktionen gehören nicht zu einer
> Sprachdefinition

Bibliotheken können sehr wohl Bestandteil eines Standards sein. Anno K&R 
wurde das de fakto so gesehen, weil das ganze Buch als Standardwerk 
betrachtet wurde.

Ab ANSI-C waren bestimmte Includes und ihre Inhalte definitiv Teil der 
Standards. Haarspalter könnten nun versucht sein, diesen Standard in 2 
Substandards zu differenzieren, einen für Syntax und Semantik und einen 
andere für eine mindestens erforderliche Bibliothek, aber das bringt 
nicht viel ein.

von Rolf M. (rmagnus)


Lesenswert?

W.S. schrieb:
> Rolf Magnus schrieb:
>> Ist printf deshalb kein Teil von C?
>
> Richtig. 'printf' ist genauso wie alles was in separaten Headerdateien
> steht eben kein Bestandteil der Sprache.

Sehr eigenartige Sichtweise. Ich glaube nicht, daß du die mit irgendwem 
hier teilst.

> Da zählt nur genau das, was als Schlüsselwort definiert ist und nichts,
> was in irgendwelchen Headerdateien steht. Das sind alles nur Workarounds,
> wenn es um  Datentypen geht.

Ich weiß ehrlich gesagt nicht, was daran "Workaround" sein soll. Die 
funktionieren prima und ohne Probleme.
Und es gibt keinerlei sinnvollen Grund, mit neuen Schlüsselwörtern um 
sich zu werfen, nur um eine gut funktionierende Lösung zu ersetzen durch 
etwas, das nicht besser ist.

> Auch die ganzen Funktionen der diversen Standardbibliotheken gehören
> nicht zu den Bestandteilen der Sprache, sondern sind lediglich
> "üblicherweise vorhandene Funktionen".
>
> 'printf' kann, muß aber nicht in den Libraries einer Toolchain enthalten
> sein. Nur so als Beispiel.

C definiert zwei Arten von Implementationen, nämlich "freestanding" und 
"hosted". Bei ersterer ist sehr vieles optional, bei letzerer nicht. 
Dort sind auch printf() und die ganzen Typen aus stdint.h zwingend 
vorgeschrieben und müssen bei einem konformen Compiler dabei sein. 
Sind sie das nicht, ist es kein ISO-C-Compiler.

> Es wäre ganz gewiß kein Beinbruch gewesen, 'int' als 16 Bit Zahl und
> 'long' als 32 Bit Zahl festzuschreiben. Das wäre überhaupt nicht
> inkompatibel zum Bisherigen gewesen

Mal abgesehen von Plattformen, die z.B. gar keinen 16-Bit-Typen kennen. 
Dort müßte man dann mit viel Aufwand einen solchen emulieren, was 
schnarchlahme Progrmame zur Folge hätte. Und ja, solche Plattformen gibt 
es.

> Systemvariablen und Standardfunktionen gehören nicht zu einer
> Sprachdefinition und sollen deshalb eben nicht eigene Schlüsselworte
> erhalten. Aber grundlegende Datentypen gehören zu den echten Grundlagen
> einer jeden Programmiersprache und damit in den eigentlichen
> Sprachumfang mit eigenem Schlüsselwort.

Die grundlegenden Datentypen sind ja auch da. Und für entsprechende 
Anforderungen sind eben noch Alias-Namen mit dabei, die man optional 
nutzen kann.

> Und da gibt es in C eben nix anderes als char, int und long nebst ihren
> unsigned Versionen. Alles Andere ist in C nicht definiert.

Hast du die Sprachdefinition mal gelesen?

> Warum in aller Welt wollen die hier versammelten Diskutierer das nicht
> einsehen und einfach mal sagen "ja, so isses eben."

Weil es Unsinn ist.

von Matthias (Gast)


Lesenswert?

W.S. schrieb:
> Du hast ne ziemlich seltsame Denkweise, die ich nicht teile.
> Als Programmierer muß man sich auf die verwendeten Datentypen verlassen
> können, was in C nicht der Fall ist.

Du besitzt eine interessante "Meinung" und fundiertes Halbwissen. 
Respekt. Leider wird diese Meinung allerdings nicht von der C-Idee 
getragen. C ist immer und wird immer eine möglichst hardwarenahe Sprache 
sein.

Solltest Du den von dir propagierten Grad an Abstraktion und 
Typensicherheit brauchen musst du ein anderes Sprachmittel wählen. 
Vielleicht ist JAVA was für dich.
Der Standard gibt für seine Typen durchaus einen begrenzten Wertebreich 
an. Wenn ich Variablen in diesen Wertebereich deklariere kann ich dem 
Compiler die Wahl eines möglichst natürlichen Formats für die Maschine 
lassen.
Für exakt definierte Typen braucht es allerdings plattformangepasste 
Typendefinitionen, wie in den Strukturen für Kommunikationsprotokolle. 
Das kannst du getrost deinem Compilerhersteller überlassen, denn der 
liefert ja das stdint.h mit.
Und im Grunde kommen diese Strukturen eh nicht ohne deinen Einfluss auf 
den Compiler aus (du musst mit #pragma meistens das Padding verhindern).

von Andreas D. (rackandboneman)


Lesenswert?

"Es wäre ganz gewiß kein Beinbruch gewesen, 'int' als 16 Bit Zahl und "

Int steht nunmal für "ein Maschinenwort ala Maison, egal wie gross das 
ist solang da 16 Bit reinpassen", und das ist ein sinnvoller Typ, warum 
sollte man das anders handhaben?

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

W.S. schrieb:
> Rolf Magnus schrieb:
>> Ist printf deshalb kein Teil von C?
>
> Richtig. 'printf' ist genauso wie alles was in separaten Headerdateien
> steht eben kein Bestandteil der Sprache.

Zu einer Sprache gehört alles, was in der Spech-Spezifikation steht

> Da zählt nur genau das, was als Schlüsselwort definiert ist und
> nichts, was in irgendwelchen Headerdateien steht. Das sind alles
> nur Workarounds, wenn es um Datentypen geht. Auch die ganzen
> Funktionen der diversen Standardbibliotheken gehören nicht zu den
> Bestandteilen der Sprache, sondern sind lediglich "üblicherweise
> vorhandene Funktionen".

Eine Sprache in Sprachkern und Bibliotheken aufzuspalten ist nun 
wirklich kein Nachteil von C.

Das gleiche Konzept findet sich bei C++, Fortran, Java, Ada, Python und 
zig anderen Sprachen, denn es ist überaus sinnvoll, einen kompakten und 
überschaubaren Sprachken zu haben.

Da es dir um dein Hobby C-Bashing geht: C hat wahrlich genug Schwächen 
und Kritikpunkte, so daß es wirklich nicht erforderlich ist, 
Kritikpunkte an den Haaren herbei zu ziehen.  Die Aufteilung in 
Sprachkern und Standard-Bibliothek und -Header gehört nämlich nicht zu 
den Schwächen, sondern zu den Stärken der Sprache.

Beitrag #5409776 wurde von einem Moderator gelöscht.
Dieser Beitrag ist gesperrt und kann nicht beantwortet werden.