Meta-Programmierung: char und int8_t



  • Folgendes ist mir beim Rumspielen mit MetaProgrammierung aufgefallen:

        char c;
        std::cout << std::is_same<decltype(c), int8_t>::value << std::endl;
        std::cout << std::is_same<decltype(c), char>::value << std::endl;
    
        int i;
        std::cout << std::is_same<decltype(i), int>::value << std::endl;
        std::cout << std::is_same<decltype(i), int32_t>::value << std::endl;
    

    Ergibt: 0111

    D.h. ein char ist kein int8_t
    aber ein int ist ein int32_t

    Wtf?

    Ist das jetzt bei mir nur ein Compilerspezifisches Thema, oder ist das generell so? Ich ging ursprünglich davon aus, dass die int**_t-Typen eigentlich nur Typedefs sind ?

    Kann mir hier jemand Nachhilfe geben? 🙂



  • @It0101 int8_t wird ein signed char sein.
    uint8_t ein unsigned char.
    Das sind Ganzzahltypen mit kleinem Wertebereich.

    char ist der Typ für Zeichen.



  • @It0101 sagte in Meta-Programmierung: char und int8_t:

    Ergibt: 0111

    Komisch, bei mir übersetzt das nicht. Fehlt ja auch mindestens ein main ...



  • 
    #include <iostream>
    #include <cstdint>
    
    int main()
    {
        signed char c;
        std::cout << std::is_same<decltype(c), int8_t>::value << std::endl;
        std::cout << std::is_same<decltype(c), signed char>::value << std::endl;
        int i;
        std::cout << std::is_same<decltype(i), int>::value << std::endl;
        std::cout << std::is_same<decltype(i), int32_t>::value << std::endl;
        return 0;
    }
    

    Also "signed char" passt in dem Fall zu int8_t. Aber was ist jetzt der Unterschied zwischen "signed char" und "char". Die zusätzlich Angabe von "signed" ist ja bei INT auch nicht üblich, bzw. generell unüblich. Ich ging eigentlich bisher davon aus, dass "signed char" und "char einunddasselbe sind...

    Während "int" und "signed int" offensichtlich Synonyme sind, ist das bei "signed char" und "char nicht der Fall....



  • @It0101 sagte in Meta-Programmierung: char und int8_t:

    Während "int" und "signed int" offensichtlich Synonyme sind, ist das bei "signed char" und "char nicht der Fall....

    Korrekt. Und char kann auch unsigned sein.



  • @It0101
    Interessante Beobachtung. Ich habe mal deinen Code etwas aufgebohrt:

    #include <iostream>
    #include <cstdint>
    
    
    int main(int argc, char* argv[])
    {
    	std::cout << std::endl << "*** char ***" << std::endl;
    	char c;
    	std::cout << "int8_t:\t\t" << std::is_same<decltype(c), int8_t>::value << std::endl;
    	std::cout << "uint8_t:\t" << std::is_same<decltype(c), uint8_t>::value << std::endl;
    	std::cout << "char:\t\t" << std::is_same<decltype(c), char>::value << std::endl;
    	std::cout << "signed char:\t" << std::is_same<decltype(c), signed char>::value << std::endl;
    	std::cout << "unsigned char:\t" << std::is_same<decltype(c), unsigned char>::value << std::endl;
    
    
    	std::cout << std::endl << "*** signed char ***" << std::endl;
    	signed char c1;
    	std::cout << "int8_t:\t\t" << std::is_same<decltype(c1), int8_t>::value << std::endl;
    	std::cout << "uint8_t:\t" << std::is_same<decltype(c1), uint8_t>::value << std::endl;
    	std::cout << "char:\t\t" << std::is_same<decltype(c1), char>::value << std::endl;
    	std::cout << "signed char:\t" << std::is_same<decltype(c1), signed char>::value << std::endl;
    	std::cout << "unsigned char:\t" << std::is_same<decltype(c1), unsigned char>::value << std::endl;
    
    
    	std::cout << std::endl << "*** unsigned char ***" << std::endl;
    	unsigned char c2;
    	std::cout << "int8_t:\t\t" << std::is_same<decltype(c2), int8_t>::value << std::endl;
    	std::cout << "uint8_t:\t" << std::is_same<decltype(c2), uint8_t>::value << std::endl;
    	std::cout << "char:\t\t" << std::is_same<decltype(c2), char>::value << std::endl;
    	std::cout << "signed char:\t" << std::is_same<decltype(c2), signed char>::value << std::endl;
    	std::cout << "unsigned char:\t" << std::is_same<decltype(c2), unsigned char>::value << std::endl;
    	return 0;
    }
    

    Als Ergebnis bekomme ich:

    *** char ***
    int8_t:         0
    uint8_t:        0
    char:           1
    signed char:    0
    unsigned char:  0
    
    *** signed char ***
    int8_t:         1
    uint8_t:        0
    char:           0
    signed char:    1
    unsigned char:  0
    
    *** unsigned char ***
    int8_t:         0
    uint8_t:        1
    char:           0
    signed char:    0
    unsigned char:  1
    




  • @Quiche-Lorraine Das merkt man auch, wenn man Pointer auf diese Typen nimmt.

    cout gibt bei *char einen C-String aus.



  • Danke @Quiche-Lorraine

    D.h. für mich als Konsequenz:
    Wenn ich in der Meta-Programmierung die Byte-Datentypen abprüfen will, reicht es wenn ich auf "unsigned char, signed char und char" abprüfe und habe damit auch die beiden "uint8_t" und "int8_t" erschlagen.



  • @It0101 Nimm Zeugs aus <limits>?



  • @It0101 sagte in Meta-Programmierung: char und int8_t:

    Also "signed char" passt in dem Fall zu int8_t. Aber was ist jetzt der Unterschied zwischen "signed char" und "char". Die zusätzlich Angabe von "signed" ist ja bei INT auch nicht üblich, bzw. generell unüblich. Ich ging eigentlich bisher davon aus, dass "signed char" und "char einunddasselbe sind...

    Nein, es gibt historisch gewachsen Plattformen auf denen ein char unsigned ist (Ubuntu Server auf dem Raspberry Pi ist es), und es gibt Plattformen auf denen char signed (Linux auf Intel64) ist. Deshalb gibt es diesen Dreiklang an Typen char, unsigned char und signed char. Dazu muss man aufpassen, da man auf Grund der C bzw. C++ Norm nicht voraussetzen darf, dass char 8Bit hat. Auch das ist historisch gewachsen, und es gab auch Plattformen bei denen char mehr als 8Bit hatten. UNIX verlangt mittlerweile explizit, dass char 8Bit ist.

    Deshalb ist nicht garantiert, dass man uint8_t oder int8_t synonym für char verwenden kann, bzw. diese Typen überhaupt definiert sind.


Anmelden zum Antworten