当前位置:网站首页>017 basics of C language: bit field and typedef

017 basics of C language: bit field and typedef

2022-06-27 04:25:00 Prison plan progress 50%

One : summary

Some data does not need to occupy a complete character when stored , It only needs to occupy one or several binary bits . For example, the switch only has two states: power on and power off , use 0 and 1 That is enough , That is to say, use a binary . Formally based on this consideration ,C The language also provides a data structure called bit field .

So what is a bit field ?
In the definition of structure , We can specify the number of binary digits occupied by a member variable (Bit), This is the bit domain .

for example :

struct bs{
    
	unsigned m;
	unsigned n: 4;
	unsigned char ch: 6;
}
: The following number is used to limit the number of digits occupied by the member variable . member  m  There is no limit to , According to the data type, it can be calculated that it occupies  4  Bytes (Byte) Of memory . member  n、ch  By : The following number limits ,
 You can no longer calculate length by data type , They occupy, respectively  46  position (Bit) Of memory .
n、ch  The value range of is very limited , If the data is a little bigger, it will overflow .

 example :
	#include <stdio.h>
	int main(){
    
		struct bs{
    
			unsigned m;
			unsigned n: 4;
			unsigned char ch: 6;
		} a = {
     0xad, 0xE, '$'};
		//  First output 
		printf("%#x, %#x, %c \n", a.m, a.n, a.ch);
		// Change the value and output again 
		a.m = 0xb8901c;
		a.n = 0x2d;
		a.ch = 'z';
		printf("%#x, %#x, %c\n", a.m, a.n, a.ch);
		
		return 0;
	}
 result :
	┌──(rootkali)-[~/Desktop/c_test]
	└─# ./weiyu        
	0xad, 0xe, $ 
	0xb8901c, 0xd, :

about n and ch, The first output is complete , The second output data is incomplete .

On the first output ,n、ch The values of 0xE、0x24(‘$’ Corresponding ASCII Code for 0x24), Converted to binary is 1110、10 0100, No more than the number of digits , It can output normally .

On the second output ,n、ch The value of a 0x2d、0x7a(‘z’ Corresponding ASCII Code for 0x7a), To binary, they are 10 1101、111 1010, It's out of the limit . The excess is cut off directly , be left over 1101、11 1010, Convert to hexadecimal to 0xd、0x3a(0x3a The corresponding character is :).

C Language standards , The width of a bit field cannot exceed the length of the data type it is attached to . informally , Member variables are typed , This type limits the maximum length of a member variable ,: The following number cannot exceed this length .C The language standard also states that , Only a limited number of data types can be used in bit fields . stay ANSI C in , These data types are int、signed int and unsigned int(int The default is signed int); here we are C99,_Bool It's also supported . But the compiler has been extended in the specific implementation , Extra support char、signed char、unsigned char as well as enum type , So the above code doesn't match C Language standards , But it can still be supported by the compiler .

 

Two : Bit field storage

C The language standard does not specify the specific storage mode of bit field , Different compilers have different implementations , But they all try to compress storage space .

 The specific storage rules of bit fields are as follows :
1)  When adjacent members are of the same type , If the sum of their bit widths is less than that of the type  sizeof  size , Then the next member is next to the previous member , Until it can't hold ; If the sum of their bit widths is greater than that of the type  sizeof  size ,
	 Then the following members will start with the new storage unit , The offset is an integral multiple of the size of the type .
	 In the following bit field  bs  For example :
	#include <stdio.h>
	int main(){
    
		struct bs{
    
			unsigned m: 6;
			unsigned n: 12;
			unsigned p: 4;
		};
		printf("%d\n", sizeof(struct bs));
		return 0;
	}
	 Running results :
	4
	m、n、p  The types of  unsigned int,sizeof  As the result of the  4  Bytes (Byte), That is to say  32  bits (Bit).m、n、p  The sum of the bit width of is  6+12+4 = 22, Less than  32, So they're stored next to each other , There's no gap in the middle .


2) When the types of adjacent members are different , Different compilers have different implementations ,GCC  Will compress storage , and  VC/VS  Can't .
	 Look at the bit field below  bs:
	#include <stdio.h>
	int main(){
    
		struct bs{
    
			unsigned m: 12;
			unsigned char ch: 4;
			unsigned p: 4;
		};
		printf("%d\n", sizeof(struct bs));
		return 0;
	}
	 stay  GCC  The result of running under is  4, Three members are stored next to each other ; stay  VC/VS  The result of running under is  12, The three members are stored according to their respective types ( It is the same as when the positioning width is not specified ).


3)  If members are interspersed with non bit domain members , Not so compressed . For example, for the following  bs:
	struct bs{
    
		unsigned m: 12;
		unsigned ch;
		unsigned p: 4;
	};
	 Under each compiler  sizeof  The result is  12.

 

3、 ... and : Nameless bit field

A bit domain member can have no name , Only data type and bit width are given , As shown below :

struct bs{
    
	int m: 12;
	int  : 20;  // This bit domain member cannot use 
	int n: 4;
};

Nameless bit fields are usually used to fill in or adjust the position of members . Because there is no name , Nameless bit fields cannot be used .

In the example above , If no bit width is 20 Anonymous members of ,m、n It's going to be next to the storage ,sizeof(struct bs) As the result of the 4; With this 20 Bit as fill ,m、n Will be stored separately ,sizeof(struct bs) As the result of the 8.

 

Four :typedef

C Language provides typedef keyword , Allow a new alias for a data type , It's like giving people “ nickname ” equally . The purpose of aliasing is not to improve the efficiency of the program , But for coding convenience .

For example, the name of a structure is stu, If you want to define a structure variable, you have to write it like this :struct stu stu1;

struct It seems superfluous , But if you don't write, you will report an error . If struct stu It's a nickname STU, It's easy to write :STU stu1; This way of writing is more concise , The meaning is also very clear , Whether in the standard header file or later programming practice , Will make extensive use of this alias .

Grammar format :typedef oldName newName;

 for example :
	typedef int INTEGER;
	INTEGER a, b;
	a = 1;
	b = 2;
	INTEGER a, b;  Equivalent to int a, b;
 And so on , Define an alias for the structure type :
	typedef struct stu{
    
		char name[20];
		int age;
		char sex;
	} STU;
	STU  yes  struct stu  Another name for , It can be used  STU  Define structure variables :
		STU body1,body2;
	 It is equivalent to :
		struct stu body1, body2;

difference :
typedef and #define
#define yes C Instructions , Used to define aliases for various data types , And typedef similar , But they are different :

  • typedef Limited to defining symbol names for types ,#define Not only can you define aliases for types , You can also define aliases for numbers , For example, we can define 1 by ONE
  • typedef Is interpreted by the compiler ,#define Statements are processed by the precompiler .

Here is #define The simplest use of :

#include <stdio.h>
#define TRUE 1
#define FALSE 0 
int main( )
{
    
	printf( "Value of TRUE : %d\n", TRUE);
	printf( "Value of FALSE : %d\n", FALSE);
	 
	 return 0;
}


 When the above code is compiled and executed , It will produce the following results :

Value of TRUE : 1
Value of FALSE : 0

原网站

版权声明
本文为[Prison plan progress 50%]所创,转载请带上原文链接,感谢
https://yzsam.com/2022/178/202206270404363099.html