Detailed decomposition and use of structure in C language

Table of contents

First: the definition of the structure

Second: Rules

Third: Structure declaration

Fourth: Three methods of C language structure definition

Fifth: Initialization of structure variables

Sixth: Whole and Separate

Seventh: Structure length

Eighth: In embedded development, detailed explanation of the use of C language bit structure

Ninth: Summary:


First: the definition of the structure

A structure (struct) is a data collection composed of a series of data of the same type or different types, also called a structure.

The structure is the same as other types of basic data types, such as int type and char type; but the structure can be made into the data type you want for future use.

In actual projects, structures exist in large numbers. Developers often use structures to encapsulate some properties to form new types. Since the C language cannot operate the database, a large amount of data is stored in the memory through the operation of the internal variables of the structure in the project to complete the storage and operation of the data.

In practical problems, sometimes we need several data types to modify a variable.

For example, a student's information requires student number (string), name (string), age (integer) and so on.

These data types are different, but they also represent a whole. If there is a connection, then we need a new data type-structure, which stores different types of data together and processes them as a whole.

The function of the structure in the function is not convenient, and its main function is encapsulation. The advantage of encapsulation is that it can be reused. So that users don't have to care about what this is, as long as it is used according to the definition.

The size of the structure is not just a simple addition of structure elements, because our current mainstream computers use 32Bit word-length CPUs, and it is more efficient to take 4 bytes for this type of CPU than to take one byte. , is also more convenient. Therefore, if the first address of each member in the structure is an integer multiple of 4, it will be relatively more efficient when fetching data elements, which is the origin of memory alignment.

Compilers on each particular platform have their own default "alignment factor" (also called alignment modulus). Programmers can change this coefficient by precompiling the command #pragma pack(n), n=1,2,4,8,16, where n is the "alignment coefficient" you want to specify.

Second: Rules

1. Alignment rules for data members: For data members of a structure (or union), the first data member is placed at the position where the offset is 0, and the alignment of each data member follows the value specified by #pragma pack and Among the lengths of the data member itself, the smaller one is executed.

2. The overall alignment rule of the structure (or union): After the data members have completed their respective alignment, the structure (or union) itself must also be aligned, and the alignment will follow the value specified by #pragma pack and the maximum length of the data member of the structure (or union) Of these, the smaller one carries on.

3. Combining 1 and 2, it can be deduced that when the n value of #pragma pack is equal to or exceeds the length of all data members, the size of this n value will have no effect.

In C language, a structure type can be defined, and multiple related variables can be packaged into a whole for use. Variables in a structure can be of the same, partially the same, or completely different data types. Structures cannot contain functions.

In object-oriented programming, an object has state (properties) and behavior, the state is stored in member variables, and the behavior is realized through member methods (functions). The structure in C language can only describe the state of an object, but cannot describe the behavior of an object. In C++, considering the continuity of the transition from C language to C++ language, the structure is extended. The C++ structure can contain functions. In this way, the C++ structure also has the function of a class. Unlike the class, the structure The functions contained in the body are public by default, not private.

Third: Structure declaration

//声明一个结构体 struct book {
   
     char title[MAXTITL];//一个字符串表示的titile 题目 ;  char author[MAXAUTL];//一个字符串表示的author作者 ;  float value;//一个浮点型表示的value价格;}; //注意分号不能少,这也相当于一条语句;

This declaration describes a structure consisting of two character arrays and a float variable.

Note, however, that it does not create an actual data object, but describes an element that makes up such an object.

Therefore, we sometimes call the structure declaration a template, because it outlines how the data should be stored, and does not instantiate the data object.

Let's introduce the above structure declaration;

1. First use the keyword struct, which means that the next is a structure.

2. Followed by an optional flag (book), which is a quick mark used to refer to the structure.     

So we can later create data objects like this

struct book library;//set library as a structure variable that can use the book structure, then the variable library contains all the elements in its book structure

3. Next is a curly brace, enclosing the list of structure members and each member variable, using its own declaration method to describe, and ending the description with a semicolon;

For example: char title[MAXTITL]; This is how character arrays are declared, ending with a semicolon;

Note : Each member can use any C data structure or even other structures, which is also possible;

4. The semicolon after the closing curly brace indicates the end of the structure design definition.

Regarding the location of its struct declaration, that is where this code should be placed. Again this is scoped.

If this declaration is placed outside any function, then the markup can be used in this file, and all functions after the declaration can be used.

If such a declaration is inside a function, its markup can only be used inside and after its declaration;

Regarding what we keep saying, the tag name is optional, so when can we omit it, and when must we not omit it?

If it is the method of declaration definition above, and you want to define the structure design in one place, and define the actual structure variables in other places, then you must use tags;

It can be omitted, and the structure variable is created at the same time of design, but this design is one-off.

The general format is:

struct structure name (that is, optional tag name) { member variable; }; // Use a semicolon to indicate the end of the definition.

Fourth: Three methods of C language structure definition

1. The most standard way:

#include <stdio.h>struct student //结构体类型的说明与定义分开。声明{
   
     int age;  /*年龄*/  float score; /*分数*/  char sex;   /*性别*/};int main (){
   
     struct student a={ 20,79,'f'}; //定义  printf("年龄:%d 分数:%.2f 性别:%c\n", a.age, a.score, a.sex );  return 0;}

2. Not an environmentally friendly way

#include <stdio.h>struct student /*声明时直接定义*/{
   
     int age;  /*年龄*/  float score;  /*分数*/  char sex;   /*性别*/ /*这种方式不环保,只能用一次*/} a={21,80,'n'};int main (){
   
     printf("年龄:%d 分数:%.2f 性别:%c\n", a.age, a.score, a.sex );}

3. The most helpless way

#include <stdio.h>struct   //直接定义结构体变量,没有结构体类型名。这种方式最烂{
   
     int age;  float score;  char sex;} t={21,79,'f'};int main (){
   
     printf("年龄:%d 分数:%f 性别:%c\n", t.age, t.score, t.sex);  return 0;}

define structure variable

Previously, the definition of our structure type (the declaration of the structure) just told the compiler how to represent the data, but it did not allow the computer to allocate space for it.

If we want to use the structure, we need to create variables, that is, structure variables;

Create a structure variable;

struct book library;

After seeing this instruction, the compiler will create a structure variable library. At this time, the compiler will allocate memory space for the variable according to the book template, and the storage space here is combined with this variable.

This is also when we access the structure variable members later, we will use the structure variable name to access.

analyze:

The role of struct book:

In the structure declaration, the role of struct book is the same as that of basic data type names such as int.

struct book s1,s2,*ss;

Define two structure variables of struct book structure type, and also define a pointer to the structure, whose ss pointer can point to s1, s2, or any other book structure variables.

struct book library;

Equivalent to:

struct book{
   
   char … …. ….. }library;

These two are equivalent, but the first one can reduce the amount of code written;

Now let’s go back to the question just mentioned, when can the optional identifier be omitted;

One:

struct{
   
     char title[MAXTITL];   char author[MAXAUTL];  float value;}library;

Note that here is no longer defining and declaring the structure type, but directly creating the structure variable, and the compiler will allocate memory;

In this way, the identifier, that is, the structure name, can indeed be omitted, but it can only be used once; because at this time, the process of declaring the structure and the process of defining the structure variable are combined together, and each member variable is not initialized.

This won't work if you want to use a struct module multiple times.

Second,

Use typedef to define a new type name to replace the existing type name, that is, to rename the existing type;

The general format is; typedef existing type new type name;

typedef int Elem; typedef struct{
   
   int date;    .....    .....}STUDENT;STUDENT stu1,stu2;

To summarize the definition of structure variables:

1. Define the structure type first and then define the structure variable;

The format is: struct structure name variable name list;

//注意这种之前要先定义结构体类型后再定义变量;struct book s1,s2,*ss;

2. Define the structure variable while defining the structure type;

The format is:

struct 结构体名{
   
    成员列表;}变量名列表;//这里结构体名是可以省的,但尽量别省;struct book{
   
     char title[MAXTITL];//一个字符串表示的titile 题目 ;  char author[MAXAUTL];//一个字符串表示的author作者 ;  float value;//一个浮点型表示的value价格;}s1,s2

Directly defining structure type variables is the case where the structure name is omitted in the second case;

This method cannot specify the structure type name but directly defines the structure variable, and is applicable when the structure variable is defined only once, and the structure type without the structure name cannot be reused.

That is to say, later programs can no longer define variables of this type unless a repeated struct is written.

Fifth: Initialization of structure variables

First recall the initialization of basic data types and array types:

int a = 0;int array[4] = {1,2,3,4};//每个元素用逗号隔开

Recall the array initialization problem:

Go back to the initialization of the structure variable

The initialization of structure variables is similar to the initialization of arrays;

Also use curly braces to enclose a comma-separated list of initialized items. Note that each initialization item must match the type of the structure member to be initialized.

struct book s1={//对结构体初始化   "yuwen", //title为字符串   "guojiajiaoyun", //author为字符数组   22.5     //value为flaot型 };//要对应起来,用逗号分隔开来,与数组初始化一样;

Add a little knowledge about structure initialization and storage class period: if you want to initialize a structure with static storage period, the value in the initialization item list must be a constant expression;

Note that if there is no initialization when defining the structure variable, then all of them cannot be initialized together later; meaning:

/这样是可以的,在定义变量的时候就初始化了;struct book s1={//对结构体初始化  "guojiajiaoyun",//author为字符数组  "yuwen",//title为字符串  22.5};/这种就不行了,在定义变量之后,若再要对变量的成员赋值,那么只能单个赋值了;struct book s1;s1={  "guojiajiaoyun",//author为字符数组  "yuwen",//title为字符串  22.5};//这样就是不行的,只能在定义的时候初始化才能全部赋值,之后就不能再全体赋值了,只能单个赋值;只能:s1.title = "yuwen";........//单个赋值;

For designated initialization of structs:

access structure members

The structure is like a super array. In this super array, one element can be of char type, the next element can be of flaot type, and the next element can be of int array type. These all exist.

In the array, we can access each element of an array through subscripts, so how to access each member in the structure?

Use the structure member operator dot (.) on it;

Structure variable name. Member name; 

Note that its associativity is from left to right, and it has the highest priority among all operators;

For example, s1.title refers to the title part of s1; s1.author refers to the author part of s1; s1.value refers to the value part of s1.

Then you can use s1.title like a character array, and use s1.value like a float data type;

Note that although s1 is a structure, s1.value is of type float.

Therefore, s1.value is equivalent to the variable name of the float type, and is used according to the float type;

For example:

printf(“%s\n%s\n%f”, s1.title, s1.author, s1.value); //Access structure variable elements

Note that scanf(“%d”,&s1.value); There are two operators in this statement, & and structure member operator point.

In principle, we should enclose (s1.value, because they are a whole, indicating the value part of s1) but it is the same if we do not enclose, because the priority of dot is higher than &.

If its member itself is a structure type, you can use several member operators to find the lowest-level member one by one and then operate on it;

Struct variable name. member. sub-member... the lowest-level sub-member;

struct date{
   
     int year;  int month;  int day;};struct student{
   
     char name[10];  struct date birthday;}student1;//若想引用student的出生年月日,可表示为;student.brithday.year;brithday是student的成员;year是brithday的成员;

Sixth: Whole and Separate

You can assign a structure variable as a whole to another structure variable of the same type to achieve the effect of overall assignment; the value of this member variable will be assigned to another variable as a whole;

A structure variable cannot be input and output as a whole; when inputting and outputting structure data, each member of the structure variable must be specified separately;

Summary : Except for "structure variables of the same type can be assigned to each other as a whole", in other cases, they cannot be referenced as a whole, but can only be referenced separately for each member;

Seventh: Structure length

Bytes of data type:

16 bit compiler

char: 1 byte
char* (pointer variable):  2 bytes
short int:  2 bytes
int:   2 bytes
unsigned int:  2 bytes
float:   4 bytes
double:    8 bytes
long:    4 bytes
long long:   8 bytes
unsigned long:   4 bytes

32-bit compiler

char: 1 byte
char* (pointer variable):  4 bytes (32-bit addressing space is 2^32, that is, 32 bits, that is, 4 bytes. Similarly for 64-bit compiler)
short int: 2 bytes
int:   4 bytes
unsigned int:  4 bytes
float:   4 bytes
double:    8 bytes
long:    4 bytes long long:   8 bytes
unsigned long :   4 bytes

So, how many bytes does the following structure type occupy?

typedef struct{
   
     char addr;  char name;  int  id;}PERSON;

Through printf("PERSON length=%d bytes\n", sizeof(PERSON)); you can see the result:

Struct Byte Alignment

Through the following method, you can clearly know why it is 8 bytes.

1. Define an array of 20 char elements

char ss[20]={0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29};

2. Define the pointer ps of the structure type to point to the ss array

PERSON *ps=(PERSON *)ss;

3. Print out each member

printf("0x%02x,0x%02x,0x%02x\n",ps->addr,ps->name,ps->id);printf("PERSON长度=%d字节\n",sizeof(PERSON));

It can be seen that both addr and name occupy only one byte, but they are less than 4 bytes, and the value of id is only after skipping 2 bytes, which is 4-byte alignment. The structure members have int type and will be automatically aligned according to 4 bytes.

Swap the order of structure members

typedef struct{
   
     char addr;  int  id;  char name;}PERSON;

output:

Arrange in the following order:

typedef struct{
   
   int  id;char addr;char name;}PERSON;

output:

It can be seen that the order of structure members is optimized to save space.

If all members are of char type, they will be aligned according to 1 byte, ie

typedef struct{
   
   char addr;char name;  char  id;}PERSON;

Output result:

structure nesting

Structure nested structure method:

typedef struct{
   
     char addr;  char name;    int  id;}PERSON;typedef struct{
   
     char age;  PERSON  ps1;}STUDENT;

First define the structure type PERSON, and then define the structure STUDENT, PERSON as one of its members.

According to the previous method, print the value of each member.

1. Define the STUDENT pointer variable to point to the array ss

STUDENT *stu=(STUDENT *)ss;

2. Print out each member and length

printf("0x%02x,0x%02x,0x%02x,0x%02x\n",stu->ps1.addr,stu->ps1.name,stu->ps1.id,stu->age);printf("STUDENT长度=%d字节\n",sizeof(STUDENT));

Swap the order of STUDENT members,

typedef struct{
   
     PERSON  ps1;  char age;}STUDENT;

Output result:

In fact, there is nothing too unexpected about the nesting of structures, as long as certain rules are followed:

//对于“一锤子买卖”,只对最终的结构体变量感兴趣,其中A、B也可删,不过最好带着  struct A{     struct B{               int c;            }b;  }a;  //使用如下方式访问:a.b.c = 10;

In particular, you can define structure B while using it:

struct A{
   
       struct B{
   
          int c;          }b;struct B sb;}a;  

How to use and test:

a.b.c = 11;  printf("%d\n",a.b.c);  a.sb.c = 22;  printf("%d\n",a.sb.c);

The result is correct.

However, if the nested structure B is declared inside A, and a corresponding object entity b is not defined, the size of the structure B is still not included in the structure A.

Occupies memory space

The struct structure cannot apply for memory space when the structure is defined, but if it is a structure variable, it can be allocated when it is declared-the relationship between the two is like a C++ class and object, and the object allocates memory (but strictly speaking, As a code segment, does the structure definition part ".text" really take up no space? Of course, this is a topic in another category).

The size of a structure is usually (just usually) the sum of the sizes of the variables contained in the structure. The following prints the size of the above structure:

printf("size of struct man:%d\n",sizeof(struct man));  printf("size:%d\n",sizeof(Huqinwei));

There is no suspense in the result, they are all 28: 20 for the char array, 4 for the int variable, and 4 for the floating point variable.

Let's talk about unusual situations

For relatively small members in the structure, they may be forcibly aligned, resulting in vacant space, which is related to the mechanism of reading memory.

For the sake of efficiency, usually 32-bit machines are aligned by 4 bytes, and those smaller than 4 bytes are regarded as 4 bytes. If there are consecutive ones smaller than 4 bytes, you can not rush to align them. Wait until you have enough and add the next element beyond an alignment position. Start to adjust, such as 3+2 or 1+4, the latter needs to be started separately (the size of the structure below is 8bytes), there are many related examples, so I won’t go into details.

struct s{
   
     char a;    short b;    int c;  };

Correspondingly, 64-bit machines are aligned by 8 bytes. However, the alignment is not absolute. Use #pragma pack() to modify the alignment. If it is changed to 1, the size of the structure is the sum of the actual member variable sizes.

Unlike C++ classes, structures cannot initialize variables inside structures.

The following is an example of the error:

#include<stdio.h>  //直接带变量名struct stuff{
   
   //      char job[20] = "Programmer";  //      char job[];  //      int age = 27;  //      float height = 185;  };

PS: The declaration of the structure should also pay attention to the position, the scope is different.

The declaration and definition of structure variables in C++ are slightly different from those in C. To put it bluntly, they are more "object-oriented" and less demanding.

Why some function parameters are structure pointer type

If the function has many parameters, it is easy to generate "duplicate C language code", for example:

int get_video(char **name, long *address, int *size, time_t *time, int *alg){
   
       ...}int handle_video(char *name, long address, int size, time_t time, int alg){
   
       ...}int send_video(char *name, long address, int size, time_t time, int alg){
   
       ...}

The above C language code defines three functions: get_video() is used to obtain a piece of video information, including: video name, address, size, time, and encoding algorithm.

Then the handle_video() function processes the video according to these parameters of the video, and then send_video() is responsible for sending the processed video. Here is a call:

char *name = NULL;long address;int size, alg;time_t time;get_video(&name, &address, &size, &time, &alg);handle_video(name, address, size, time, alg);send_video(name, address, size, time, alg);

Judging from the above C language code, in order to complete a video "acquisition"-"processing"-"send" operation, the C language program has to define multiple variables, and these variables need to be repeated at least three times.

Although the code style of C language programs varies from person to person, "duplicate code" should always be avoided as much as possible. In any case, every time these functions are used, many temporary variables need to be defined, which is always very troublesome. Therefore, in this case, you can use the structure syntax of C language:

struct video_info{
   
     char *name;  long address;  int size;  int alg;  time_t time;};

After defining the video_info structure, the parameters of the above three C language functions can be written as follows, see:

int get_video(struct video_info *vinfo){
   
       ...}int handle_video(struct video_info *vinfo){
   
       ...}int send_video(struct video_info *vinfo){
   
       ...}

The modified C language code is significantly more streamlined. Inside the function, various information of the video can be accessed through the structure pointer vinfo, for example:

printf("video name: %s\n", vinfo->name);long addr = vinfo->address;int size = vinfo->size;

In fact, after using the structure video_info to encapsulate the parameters of the video information, calling these modified functions is also very simple:

struct video_info vinfo = {0};get_video(&vinfo);handle_video(&vinfo);send_video(&vinfo);

As can be seen from the above C language code, only one temporary variable needs to be defined to use the modified function, and the entire code becomes very streamlined.

Readers should notice that the prototypes of the handle_video() and send_video() functions before modification are as follows:

int handle_video(char *name, long address, int size, time_t time, int alg);int send_video(char *name, long address, int size, time_t time, int alg);

According to this C language code, we know that the handle_video() and send_video() functions only need to read the parameter information, and no longer modify the parameters, so why use the structure video_info to encapsulate the data, the modified handle_video() and send_video() functions The parameter is struct video_info * pointer type?

int handle_video(struct video_info *vinfo);int send_video(struct video_info *vinfo);

Since the handle_video() and send_video() functions only need to read the parameter information, then we don't need to use the pointer type anymore? Indeed, it is also possible to directly use the struct video_info type as the parameters of these two functions:

int handle_video(struct video_info vinfo){
   
       ...}int send_video(struct video_info vinfo){
   
       ...}

It seems that the difference between this writing method and the use of struct video_info *pointer parameters is nothing more than a change in the way of accessing data inside the function. However, if readers can think of the "stack frame" concept of the C language function we discussed before, they should be able to find that the handle_video() and send_video() functions using pointer parameters are more efficient and have less overhead.

Eighth: In embedded development, detailed explanation of the use of C language bit structure

In embedded development, it is often necessary to represent various system states, and the appearance of the bit structure greatly facilitates us, especially when performing some hardware layer operations and data communication. But in the process of using the bit structure, do you think deeply about its related attributes? Is its convenience really used to improve system efficiency?

Some related experiments will be carried out below (here the actual code in project development is taken as an example):

1. Bit structure type design

//data structure except for number structure  typedef struct symbol_struct  {    uint_32 SYMBOL_TYPE   :5;  //data type,have the affect on "data display type"    uint_32 reserved_1    :4;    uint_32 SYMBOL_NUMBER  :7;  //effective data number in one element    uint_32 SYMBOL_ACTIVE  :1;//symbol active status       uint_32 SYMBOL_INDEX   :8;  //data index in norflash,result is related to "xxx_BASE_ADDR"    uint_32 reserved_2     :8;  }SYMBOL_STRUCT, _PTR_ SYMBOL_STRUCT_PTR;

Analysis: A bit structure type SYMBOL_STRUCT is defined here, so what attributes are the variables defined with this type?

Look at the results of the operation below: 

WORDS is defined as another outer type definition encapsulation, which can be treated as a variable. The addresses of the first five data fields in the WORDS variable are all 0x1ffff082c, while the address of reserved_2 is 0x1fff0830, and the pressurestate variable next to it is 0x1fff0834.

At first I thought: reserved_1 and SYMBOL_TYPE are not in the same address, because they have 9 bits in 5+4, which exceeds 1 byte address, but they actually share the first address; and reserved_2 only defines 8 bits, and it actually occupies 4 Byte (0x1fff0834 - 0x1fff0830), I originally wanted him to occupy 1 byte.

WORDS as a whole occupies 8 bytes (0x1fff0834 - 0x1fff082c), and design-time analysis occupies 5 bytes:

SYMBOL_TYPE 1; reserved_1 1;

SYMBOL_NUMBER+SYMBOL_ACTIVE 1;

SYMBOL_INDEX 1; reserved_2 1;

uint_32 reserved_2: 8;   occupies 4 bytes, it is estimated that uint_32 is working, and the 8 bits written here are only the effective number of digits I use, and the other 24 bits are free. If you define another uint_32 reserved_3: 8 below, the address The same is true, the address is taken in units of uint_32.

In the same way, it is not surprising that the above 5 variables share an address. Moreover, the allocation of effective bits is not continuous. For example, SYMBOL_TYPE+reserved_1 has a total of 9 bits, and if it exceeds one byte, the system simply allocates two bytes to them, one for each person; SYMBOL_NUMBER+SYMBOL_ACTIVE has a total of 8 bits, and one byte is Can handle it.

2. Modify the data structure to verify the above conjecture

//data structure except for number structure  typedef struct symbol_struct  {    uint_8 SYMBOL_TYPE    :5; //data type,have the affect on "data display type"  uint_8 reserved_1     :4;    uint_8 SYMBOL_NUMBER   :7; //effective data number in one element    uint_8 SYMBOL_ACTIVE   :1; //symbol active status    uint_8 SYMBOL_INDEX    :8; //data index in norflash,result is related to "xxx_BASE_ADDR"  uint_8 reserved_2      :8;  }SYMBOL_STRUCT,_PTR_ SYMBOL_STRUCT_PTR;

The address data is as follows:

After changing to uint_8, you can see that the address space occupation is greatly reduced, and reserved_2 only occupies 1 byte (0x1fff069f - 0x1fff069e), and other variables also conform to the above conjecture. However, pay attention to the above yellow and red statements, it always feels a little bit reluctant, then I would think, the data fields of the first two variables are 9 bits, so are they actually independent? Although they are different addresses on uint_8, are they also different address spaces on uint_32? 

3. Analyze whether the data field inside the structure is continuous, see the figure below and the result 

Original assumption: Based on the conclusions of the previous two experiments, a total of 8 bytes are occupied, and the section space is occupied: (2+4)+(4+4)+(2+2+4)+(2+2)+(6 ). However, the actual effect is not as expected. Only 4 bytes are actually occupied, and the system does not allocate 4 bytes for the RESERVED variable as expected.

analyze:

These data fields add up to a total of 32 bits and occupy 4 bytes (regardless of data alignment issues). The only reason it does take 4 bytes is this: the data fields are linked in a compact fashion without any spare bits. Is this actually the case?

See the picture and result below:

Here, in order to verify whether the link is compact, a union data is used. I will talk about that using union will not have any impact on the data organization method. It is actually the same as the last time, and it can also be analyzed.

It is mainly to analyze whether the second and third data domains are closely linked. OBJECT_ACTIVE_PRE is assigned a value of 0b00001111, NUMBER_ACTIVE is assigned a value of 0b00000101, and other variables are all 0, see the WORD value 0b1011111000000. Analyzing the WORD data, we can see that this MCU is still in the little-endian format (the high-order data is at the high end, and the low-order data is at the low end, and the big and small endian are not discussed here), and the disconnected data becomes (0)10111 11000000, which is exactly 0101+1111 , the OBJECT_ACTIVE_PRE data field spans two bytes, which is not what was originally imagined. This confirms the conclusion of the tight link above, and also conforms to the output of the data results. 

4. Experiment again to analyze whether the data is closely linked, see the figure and results below 

It can be seen that the RESERVED data field no longer belongs to the 4 address spaces (0x1fff0518 - 0x1fff051b), but they still add up to 32 bit fields. This shows that there must be a "gap" in the middle of the data. Where is the gap? Look at NUMBER_STATE, if it is close, it should be on the same byte address as NUMBER_ACTIVE, but they are not together, the "gap" exists here.

What is the difference between these two structures? The data types are inconsistent, one is uint_32 and the other is uint_8.

To sum up : the data type affects the size unit of the compiler when allocating physical space, uint_32 is 4 bytes as the unit, and the following bit field refers to the compactness in the allocated physical space When the physical space cannot satisfy the bit field, the system allocates the physical space again in a certain size unit, which is the uint_8 or uint_32 mentioned above.

For example: In the case of uint_32 above, no matter whether these bit fields are in a byte address or not, if they can be compactly allocated in a 4-byte space, they can be directly compactly allocated. If not, continue to allocate (the total space exceeds 4 bytes), allocate again with 4 bytes of space, and build a new bit field on the new address space (that is on entry 1). When uint_8, it is obvious that if the bit field cannot be compactly placed in a byte space, then a new 1-byte space size is re-allocated, the reason is the same. 

5. Does the combination of structures and unions affect the above conclusions? 

It can be seen that the system did not change the allocation strategy to squeeze the bit fields into 4 bytes because of the 4-byte variable or union type of uint_4 on the bit structure. It seems that they have no substantial connection . Here, changing uint_32 to uint_8, or replacing the bit structure, it has been proved by my experiments that it has no effect. 

Ninth: Summary:

1. When operating the bit structure, pay attention to whether the bit field of the variable is in a variable type (uint_32 or uint_8), and judge the occupied space.

2. In addition to the bit field, pay attention to the variable definition type, because the compiler space allocation is always allocated according to the type, the bit field only points out the effective bits (less than the type space), and if the bit field is larger than the type space, the compiler directly Report an error (such as uint_8 test: 15, you can experiment by yourself).

3. These two factors both affect the size of the space occupied by variables. Specifically, it can be combined with the debug window to analyze and judge through address allocation.

4. The most important point : All the above results are based on my own analysis of CodeWarrior10.2 and MQX3.8. Different compilation environments and operating systems may have different results; and even if the environment is the same , compiler configuration and optimization options may affect the system processing results. The conclusion is not important. I mainly want to tell you about this hidden trap. When dealing with similar problems in the future, you must pay attention to analysis and avoidance and master the methods.

Guess you like

Origin blog.csdn.net/weixin_41114301/article/details/130271192