C 내장 정수

29334 단어 integersbooleanc
정수 데이터 유형, 외부 라이브러리가 필요하지 않습니다.


목차
  • void
  • char
  • short
  • int
  • long
  • long long
  • _Bool

  • enum
  • enum vs #define
  • enum , flags and bitwise




  • 무효의

    void data type is used in these situations:

    • A function that does not return any value:

        void doSomething( int iNum );
      
    • A function that does not accept any parameter:

        int doSomething( void );
      
    • A pointer to void, generic pointer that has no type and represent an address of an object, that can be casted to any type.

        void *pMyPointer;
      
    • Don't you dare to sizeof(void) , but you can sizeof(*void) . Some compilers allow sizeof(void) but this is not in the ISO standard.

    In some contexts char is used to handle numerics, because is large enough to hold the number, and uses less memory than an int .

    짧은

    • short , short int , signed short and signed short int are the same thing.
    • unsigned short and unsigned short int are the same thing.

    정수

    • int , signed and signed int are the same thing.
    • unsigned and unsigned int are the same thing.

    • long , signed long , long int , and signed long int are the same thing.
    • unsigned long and unsigned long int are the same thing.

    긴 긴 [C99]

    • long long , signed long long , long long int , and signed long long int are the same thing.
    • unsigned long long and unsigned long long int are the same thing.

    _불 [C99]

    Name Characteristic Dependence in stdbool.h Value
    _Bool Native type Don't need header
    bool Macro Yes Translate to _Bool
    true Macro Yes Translate to 1
    false Macro Yes Translate to 0
    • _Bool or bool ? Both are fine, but bool looks better than the keyword _Bool .
    • Accepted values for bool and _Bool are: false or true . Assign 0 or 1 instead of false or true is valid, but is harder to read and understand.
    • _Bool is NOT unsigned int , but is part of the group unsigned integer types. It is large enough to hold the values 0 or 1 .
    • A macro to tell if the macros bool , true and false are available is __bool_true_false_are_defined , that translate to 1 .

        #if 1 != __bool_true_false_are_defined
          #include <stdbool.h>
        #endif
      
        int main(void) {
        bool x = true;
      
        if(false == x)
            return 1;
          else
            return 0;
        }
      
    • Assigning an scalar type to _Bool or bool , if the scalar value is equal to 0 or compares to 0 it will be 0 , otherwise the result is 1 .

        #include <stdio.h>
      
        int main(void) {
          _Bool x = 9; // 9 is converted to 1
          printf("%d", x); // Output 1
          return 0;
        }
      
    • _Bool has size of 1 byte, but not all bits are used. The programmer may try to use the other bits, but is not recommended, because the only guaranteed that is given is that only one bit is use to store the data, not like the type char that have 8 bits available.

    • DO NOT, but yes, you are able to redefine bool , true and false but is not a good idea. This ability is considered obsolescent and will be removed in future.

    열거

    Components of an enum :

    enum identifier { enumerators } Tag ;

    enum identifier { enumerators , } Tag ; [C99]

    typedef enum identifier { enumerators } Alias ;

    typedef enum identifier { enumerators , } Alias ; [C99]

    • Identifier: optional, with no identifier enum { BLUE }; or with identifier enum color { BLUE };
    • Enumerators: not optional, one or many integers constant. Shall be any value that is representable by int . The int value can be left to the compiler to decide, or may be defined by the programmer BLUE=11 . The default behavior if no value is defined, the first will have value 0 and the subsequent enumerator will be the previus value + 1. Yes, you can have enumerators with duplicated values.

      // BLUE is 0, GREEN is 1, Grey is 2
      enum { BLUE, GREEN, GREY };
      
      // BLUE is 0, GREEN is 15, Grey is 16, RED is 3, BLACK is 4, WHITE is 19
      enum { BLUE, GREEN = 15, GREY, RED = 3, BLACK, WHITE = RED+GREY };
      
      // BLUE is 0, GREEN is 12, Grey is 12
      enum { BLUE, GREEN = 12, GREY = 12 };
      
    • [C99] The last enumerator can be left with comma at the end , . Because makes easy to handle the enumerator using copy/paste or a script. This eliminates the need for conditional logic to handle the last enumerator.

      enum { BLUE, GREEN };   // Valid before and after C99
      enum { BLUE, GREEN, };  // Only valid after C99
      
    • Tag: optional. None, one or many tags separated by comma , . But if you have a typedef the tag part is not a tag anymore, it is alias for that type.

      enum { BLUE, GREEN } LED1, LED2; // Tags
      enum { WHITE, RED } LED3;        // Tag
      enum color { GREY, ORANGE };     // No tag
      
      LED1 = GREEN;
      LED2 = BLUE;
      LED3 = RED;
      enum color LED4 = GREY;
      
    • Alias of a type enum is done by using the keyword typedef , in simple words means that a new name for this boring_name is a awesome_name . Using typedef in the same line if you have tags, the tags are not tags anymore, instead they are alias an behave different than a tag.

      // Giving a name to a enum with no identifier
      typedef enum { BLUE } color;
      color LED = BLUE;
      
      typedef enum color { BLUE } c;
      c LED = BLUE; // or `enum color LED = BLUE;`
                    // since you have typedef there is no reason to use this way
      
      // The enum exist before the typedef
      enum color { BLUE } LED2;
      typedef enum color c;
      c LED1 = BLUE;
      LED2 = BLUE; // LED2 still a tag    
      

    Assigning a value to a variable of enum type may cause a warning during compilation. Why?

    • enum is not a type safe, and the programmer can assign any number that is not one of the _enumerators, it will compile, but this kind of error, wrong value range, is hard to debug.
    • Use an explicit cast to suppress the warning. This is one of the few cases that an explicit cast is recommended.

      enum color { BLUE=0, GREEN, RED, } LED1 ;
      LED1 = (enum color)BLUE;   //Explicit cast to suppress compiler warning.
      

    하지마



    따르지 말아야 할 예:

    // Don't use comma on last enumerator if
    // you are strict compilling to C98/C90
    enum { BLUE, };
    
    // No enum keyword used
    color { BLUE };
    
    // No enumerator declared
    enum color {};
    enum {};
    
    // Use a tag as a type for a new variable.
    enum { BLUE } LED;
    LED myLed = BLUE;
    
    // No forward-declarations, only struct and union can use this style.
    enum color;
    color { BLUE };
    
    typedef enum color;
    color { BLUE };
    
    // Enumerators with the same name in the same scope.
    enum color1 { BLUE };
    enum color2 { BLUE };
    
    // Valid, but danger, avoid even if you know BLUE value is 0, use BLUE and not 0
    enum color { BLUE=0, GREEN, RED, } LED1 ;
    LED1 = 0;
    


    열거형 대 정의

    It's a programming style preference, in my opinion the enum code is cleaner, easier to understand and debug than the macro #define for cases that represent a group of related data.

    enum { BLUE=0, RED, GREEN, };
    
    #define BLUE    0
    #define RED     1
    #define GREEN   2
    

    Also goes well in switch() :

    // Declaration
    enum color { BLUE, GREEN, RED, } led_1;
    
    // Definition
    led_1 = (enum color)BLUE; // Explicit cast to suppress compiler warnings.
    
    switch(led_1) {
        case BLUE: 
            //do something
            break;
        case GREEN: 
            //do something
            break;
        case RED: 
            //do something
            break;
    }
    

    But in case you need to save every single byte, #define and char instead of enum will be better.

    #include <stdio.h>
    
    #define VALUE1 1;
    enum a { VALUE2 = 2 };
    
    int main(void) {
        char b = VALUE1;
        printf("Char: %d\nEnum: %d\n", sizeof(b), sizeof(enum a));
        return 0;
    }
    

    The output may be Char: 1 and Enum: 4 . For small numbers, to save space, in embedded a common use is char that use less bytes then an int . Make sure to check the compiler and find a balance of speed of optimized types vs saving bytes.

    열거형, 플래그 및 비트 단위

    Using enum to group flags is powerful way to produce faster and smaller binary, at the expensive to be painful to debug. Example bellow uses enumerators defined with the power of two, in that way using the bitwise operator | give a unique number for every combination you do. And it is easy read what combination is in use.

    #include <stdio.h>
    
    enum { USB = 1, WIFI = 2, SERIAL = 4 };
    
    int main(void) {
        int iFlags = USB | WIFI;
    
        switch( iFlags ) {
            case USB: // 1
                    printf("\nUSB");
                    break;
            case WIFI: // 2
                    printf("\nWIFI");
                    break;
            case SERIAL: // 4
                    printf("\nSERIAL");
                    break;
            case USB | WIFI: // 3
                    printf("\nUSB and WIFI");
                    break;
            case USB | SERIAL: // 5
                    printf("\nUSB and SERIAL");
                    break;
            case USB | WIFI | SERIAL: // 7
                    printf("\nUSB and WIFI and SERIAL");
                    break;
            case WIFI | SERIAL: // 6
                    printf("\nWIFI and SERIAL");
                    break;
        }
    
        return 0;
    }
    

    Finding if a flag is set in the flags.

    #include <stdio.h>
    
    enum { USB = 1, WIFI = 2, SERIAL = 4 };
    
    int main(void){
        int iFlags = USB | WIFI | SERIAL;
    
        if( iFlags & USB ) {
            printf("USB flag is set"); // This is the output
        } else {
            printf("USB flag is NOT set");
        }
    
        return 0;
    }
    

    References

  • N1256
  • N1570
  • N2596
  • 좋은 웹페이지 즐겨찾기