Unsigned | Signed .. Standart wenn keine Angabe



  • 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 und unsigned 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 , and unsigned 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 , and unsigned 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 Ober

    error 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 Ober

    error 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 😉



  • LordJaxom schrieb:

    Damit wollte ich zeigen dass int == signed int, aber mitnichten char == signed char (oder unsigned char).

    Welchen Sinn Du darin siehst, Du mir sagen mußt, junger Jedi (frei nach Yoda).

    Wir dürften uns alle einig sein, daß alle ganzzahligen Typen eigentlich nur signed oder unsigned sein können und das Ganze auf die unterschiedliche Interpretation des MSB hinausläuft.

    Beim Char dürfte eine Lücke (oder eine doofe Definition) im Standard dafür verantwortlich sein, daß da kein einheitlicher default ist, deswegen müssen Compiler drei Fälle unterscheiden (wohl implementation defined).

    Also normalo: Signed, bei char müssen Bytefuchser aber aufpassen.



  • LordJaxom schrieb:

    Aber dass Du auf etwas anderes kommst war mir fast klar

    wie gesagt, habs leider immer noch nicht ausprobiert, aber ich glaube dir auch so. was würde eigentlich passieren, wenn du statt adressen die variablenwerte selbst übergeben würdest? auch 3 warnings?
    🙂


Anmelden zum Antworten