Unsigned | Signed .. Standart wenn keine Angabe
-
Tim schrieb:
Bei char wird es komplizierter, da
char
,signed char
undunsigned char
drei verschiedene Typen sind...drei verschiedene typen ist etwas unglücklich ausgedrückt. 'char' kann 'signed' oder 'unsigned' sein. das ist abhängig vom compiler bzw. wie er konfiguriert ist.
-
Tim schrieb:
während z.B.
signed int
einfach nur die Kurzform von int ist.Dann wär ja die Kurzform länger?
-
dduck schrieb:
Tim schrieb:
während z.B.
signed int
einfach nur die Kurzform von int ist.Dann wär ja die Kurzform länger?
Naja, du weisst wie ich fühle
;fricky schrieb:
Tim schrieb:
Bei char wird es komplizierter, da
char
,signed char
undunsigned char
drei verschiedene Typen sind...drei verschiedene typen ist etwas unglücklich ausgedrückt. 'char' kann 'signed' oder 'unsigned' sein. das ist abhängig vom compiler bzw. wie er konfiguriert ist.
Keine Ahnung was du willst...
The three types
char
,signed char
, andunsigned char
are collectively called the character types. The implementation shall define char to have the same range, representation, and behavior as either signed char or unsigned char.
-
Tim schrieb:
Keine Ahnung was du willst...
The three types
char
,signed char
, andunsigned char
are collectively called the character types. The implementation shall define char to have the same range, representation, and behavior as either signed char or unsigned char.na, es ist doof formuliert. char ist entweder signed oder unsigned. dazwischen gibt es nix. im unterschied zu long, int, usw, die immer 'signed' sind, kann's sich der compiler-macher bei 'char' aussuchen. genau genommen gibt es keinen dritten char-typ (was ja der zweite, von dir gepostete satz aus dem standard aussagt). gäbe es einen, dann müsste er sich von signed char und unsigned char unterscheiden. ein könig z.b beim schachspiel kann entweder schwarz oder weiss sein, es gibt keinen könig mit einer dritten farbe. und irgendwas haben und gleichzeitig nicht haben (ein vorzeichen z.b.), geht erst recht nicht.
-
Achtung, es folgt jetzt ein wenig C++, das ist diese Sprache, wo es mit Sinn drei char-Typen gibt:
void foo(char){ cout<<"char\n"; } void foo(signed char){ cout<<"signed char\n"; } void foo(unsigned char){ cout<<"unsigned char\n"; } int main(){ foo((char)0); foo((signed char)0); foo((unsigned char)0); return 0; }
Ausgabe:
char signed char unsigned char
In C ists nicht so einfach. Da sind die drei Typen aber auch sinnvoll und zwar im Endeffekt aus dem gleichen Grund. char soll Zeichen darstellen und ob die signed oder nicht sind, hängt von der Plattform ab oder vom Compilerschalter. signed char und unsigned char sind für kleine Zahlen nötig. Man kann sich auf frickys Standpunkt stellen und sagen, daß während *eines* Compilerlaufs es nur zwei Typen gibt. Aber wenn man den Code dann übertragen will, wacht man möglicherweise auf. Fällt ein Baum auch um, wenn der Holzfäller taub ist?
-
Da hab' ich noch 'ne Doofmann- Frage zum Thema:
Um die Compilerunterschiede auszugleichen, gibt es so typedef- includes, die dann je nach Compiler auszufüllen sind. Die Namensgebung ist dabei wieder uneinheitlich, die einen schreiben ui32, die anderen etwas weniger schreibfaul uint32; BYTE / sBYTE hab' ich schon gesehen wie uchar oder uchar8.
Irgendwie wird da ein Kraut- und Rübenhaufen gegen den anderen ausgewechselt.
Natürlich hab' ich auch mein eigenes Süppchen gekocht - aber irgendwann will ich das mal vereinheitlichen. Was empfiehlt sich da als quasi- Standard eigentlich für die Typenbezeichner?
-
Nimm die C99-Typen: uint8_t, uint16_t, uint32_t, uint64_t
-
volkard schrieb:
Achtung, es folgt jetzt ein wenig C++, das ist diese Sprache, wo es mit Sinn drei char-Typen gibt:
void foo(char){ cout<<"char\n"; } void foo(signed char){ cout<<"signed char\n"; } void foo(unsigned char){ cout<<"unsigned char\n"; } int main(){ foo((char)0); foo((signed char)0); foo((unsigned char)0); return 0; }
Ausgabe:
char signed char unsigned char
wie ist es eigentlich mit:
foo('a'); foo(12); foo(-99);
werden dann auch die funktionen aufgerufen, die man vielleicht erwarten würde?
volkard schrieb:
Man kann sich auf frickys Standpunkt stellen und sagen, daß während *eines* Compilerlaufs es nur zwei Typen gibt. Aber wenn man den Code dann übertragen will, wacht man möglicherweise auf.
so gesehen gibt es auch verdammt viele 'int', im schlimmsten fall pro compiler und plattform einen, die dem dornröschenschlaf ein jähes ende bescheren können. alle sind zwar 'signed', aber angefangen bei 16bit ints, über 17,18, usw. wäre 'ne menge vertreten. ich glaube trotzdem nicht dass im standard irgendwo steht: The 112 types 'int' are collectively called the int-types...
-
;fricky schrieb:
wie ist es eigentlich mit:
foo('a'); foo(12); foo(-99);
werden dann auch die funktionen aufgerufen, die man vielleicht erwarten würde?
Na, sicher.
-
volkard schrieb:
Na, sicher.
bei mir nicht. foo(12) und foo(-99) geben:
error C2668: 'foo' : ambiguous call to overloaded function
could be 'void foo(unsigned char)'
or 'void foo(signed char)'
or 'void foo(char)'soviel zum 'sinn' dieser char-dreifaltigkeit in C++
-
-12 und 99 sind int-Literale, es passiert also genau das richtige.
-
;fricky schrieb:
volkard schrieb:
Na, sicher.
bei mir nicht. foo(12) und foo(-99) geben:
error C2668: 'foo' : ambiguous call to overloaded function
could be 'void foo(unsigned char)'
or 'void foo(signed char)'
or 'void foo(char)'soviel zum 'sinn' dieser char-dreifaltigkeit in C++
Das ist aber das erwartete Verhalten. Und sinnvoll ist es sogar auch.
-
;fricky schrieb:
[...]
Dass solche Antworten kommen würden, waren mir sowas von klar, dass ich schon nach Tims Posting ein C-Beispiel dafür gebastelt hatte. Leider habe ich das aus Zeitnot nicht mehr posten können.
void cFunc( char* c ) { ((void)c); } void iFunc( int* i ) { ((void)i); } int main() { signed char a; unsigned char b; signed int c; unsigned int d; cFunc( &a ); cFunc( &b ); iFunc( &c ); iFunc( &d ); return 0; }
Dreimal darfst Du raten (am besten fängst Du dabei bei "eins" an, dann ist die dritte Antwort die korrekte), wieviele Warnungen ein standardkonformer Compiler auf höchster Warnstufe, z.B. der gcc, bei diesem Code ausgibt.
(P.S.: Der MSVC ist ein C++-Compiler, der von früher noch ein bisschen C kann und zählt damit nicht :p :D)
-
Bashar schrieb:
-12 und 99 sind int-Literale, es passiert also genau das richtige.
volkard schrieb:
Das ist aber das erwartete Verhalten. Und sinnvoll ist es sogar auch.
erwarten tut man's nur, wenn man's vorher schon weiss. intuitiv ist das verhalten keineswegs. seltsamerweise klappts aber mit allen 3 aufrufen, sobald ich bis auf 'foo(char)' die anderen funktionen auskommentiere. wieso ist ein c++ compiler schlau genug, um mit int-literalen eine 'char'-funktion aufzurufen, streikt aber, sobald überladungen da sind. er könnte doch an den parametern erkennen, was gemeint ist. konsequenterweise sollte er dann auch den aufruf der char-funktion mit int-literalen verweigern.
LordJaxom schrieb:
void cFunc( char* c ) { ((void)c); } void iFunc( int* i ) { ((void)i); } int main() { signed char a; unsigned char b; signed int c; unsigned int d; cFunc( &a ); cFunc( &b ); iFunc( &c ); iFunc( &d ); return 0; }
Dreimal darfst Du raten (am besten fängst Du dabei bei "eins" an, dann ist die dritte Antwort die korrekte), wieviele Warnungen ein standardkonformer Compiler auf höchster Warnstufe, z.B. der gcc, bei diesem Code ausgibt.
hab's nicht ausprobiert, aber ich schätze er wird mal 'signed/unsigned-mismatch' und mal sowas wie 'truncation' anmeckern. oder meintest du was anderes?
-
;fricky schrieb:
erwarten tut man's nur, wenn man's vorher schon weiss. intuitiv ist das verhalten keineswegs. seltsamerweise klappts aber mit allen 3 aufrufen, sobald ich bis auf 'foo(char)' die anderen funktionen auskommentiere. wieso ist ein c++ compiler schlau genug, um mit int-literalen eine 'char'-funktion aufzurufen, streikt aber, sobald überladungen da sind. er könnte doch an den parametern erkennen, was gemeint ist. konsequenterweise sollte er dann auch den aufruf der char-funktion mit int-literalen verweigern.
Denk doch mal selber nach.
Wenn der Laden nur eine Pizza führt, reicht es "Pizza" zu bestellen.
Wenn er aber drei verschiedene Pizzen führt, und Du "Pizza" bestellt, sagt der Obererror C2668: 'Pizza' : ambiguous call for overloaded food could be 'Pizza Hawaii' or 'Pizza Margeritha' or 'Pizza Calzone'
-
volkard schrieb:
;fricky schrieb:
erwarten tut man's nur, wenn man's vorher schon weiss. intuitiv ist das verhalten keineswegs. seltsamerweise klappts aber mit allen 3 aufrufen, sobald ich bis auf 'foo(char)' die anderen funktionen auskommentiere. wieso ist ein c++ compiler schlau genug, um mit int-literalen eine 'char'-funktion aufzurufen, streikt aber, sobald überladungen da sind. er könnte doch an den parametern erkennen, was gemeint ist. konsequenterweise sollte er dann auch den aufruf der char-funktion mit int-literalen verweigern.
Denk doch mal selber nach.
Wenn der Laden nur eine Pizza führt, reicht es "Pizza" zu bestellen.
Wenn er aber drei verschiedene Pizzen führt, und Du "Pizza" bestellt...sagt der Obererror C2668: 'Pizza' : ambiguous call for overloaded food could be 'Pizza Hawaii' or 'Pizza Margeritha' or 'Pizza Calzone'
nicht ganz, in unserem beispiel bestelle ich z.b. pizza(99) mit ananas(-), also geht der pizzafahrer in die küche und ruft 'einmal pizza mit' ananas. der koch, dessen repertoire nur aus 3 pizzen besteht überlegt kurz: pizza==char könnte sein, calzone, ohne ananas == unsigned char, nee das passt nicht, hawaii mit ananas == signed char -> das muss es sein. bingo! also schmeisst er 'ne hawaii in den ofen und ich kriege meine pizza mit ananas.
-
Die Idee ist, dass bestehender Code nicht falsch wird, wenn eine Überladung hinzugefügt wird.
BTW ist das hier extrem OT.
-
Bashar schrieb:
Die Idee ist, dass bestehender Code nicht falsch wird, wenn eine Überladung hinzugefügt wird.
das scheint aber nicht zu funktionieren.
zuerst:void foo (int) { cout<<"richtig\n"; } int main () { foo('a'); }
irgendwann später:
void foo (int) { cout<<"richtig\n"; } void foo (char) { cout<<"falsch\n"; } int main () { foo('a'); }
-
In dem Beispiel von LordJaxom wird dem Compiler die char- Sache wurscht, sobald man nicht typisierte Pointer, sondern Werte in die Funktion stopft, da ist dann Schluß mit Typüberwachung.
Vermutlich nur so eine Sache mit der möglichen Sonderrolle von char* als String.In C99 gibt's ja auch nur int8_t und uint8_t als Ersatzbezeichner, der dritte Typ ist nur Compiler- Folklore.
-
pointercrash() schrieb:
In dem Beispiel von LordJaxom wird dem Compiler die char- Sache wurscht, sobald man nicht typisierte Pointer, sondern Werte in die Funktion stopft, da ist dann Schluß mit Typüberwachung.
Richtig.
;fricky schrieb:
hab's nicht ausprobiert, aber ich schätze er wird mal 'signed/unsigned-mismatch' und mal sowas wie 'truncation' anmeckern. oder meintest du was anderes?
Falsch.
Er meckert drei mal "Pointers differ in signedness".
Damit wollte ich zeigen dass int == signed int, aber mitnichten char == signed char (oder unsigned char). Aber dass Du auf etwas anderes kommst war mir fast klar