1, #define macro

They are not part of C, but C programs need them. #define is used to define a macro, and the program replaces the contents defined by define during the preprocessing phase. Therefore, when the program runs, there is no constant defined by DEFINE in the constant table, and the system does not allocate memory for it. The constant defined by define, which is simply replaced during preprocessing, is used to define an identifier as a string, called the macro name, and the string defined as the replacement text. , so it does not check macro definitions at compile time, and the scope does not affect access to constants. Its constant value can only be a string or a number. This command comes in two formats: a simple constant macro definition and a macro definition with parameters.

Macros without arguments: # define < name > < value > note, the semicolon at the end of no, because not C statement, the name must be a word, the value can be all sorts of things, the macro definition is expressed in macro name to a string, in the macro expansion when the string to replace the macro name again, this is just a simple substitution, can contain any character in the string, can be a constant, It can also be an expression that is not checked by the preprocessor. Errors, if any, can only be detected when compiling the source program that has been expanded by the macro.

Note that a macro definition is not a description or statement and does not need a semicolon at the end of the line. If a semicolon is added, the semicolon is also replaced. Macro definitions are scoped to the end of the source program for macro definition commands. To terminate its scope, use the #undef command

Parameter macros are defined as follows: #define macro name (parameter list) string, also a semicolon, can take multiple arguments, #define NB (a, b) ((a)>(b)? (b):(a)), you can also combine (nest) other macros. Note the rule of parameter macros: everything should have parentheses, and arguments should have parentheses everywhere. Macros with arguments are common in large program code. With the help of the # and ## operators, they can be complicated, such as “generate function”, but some macros are replaced by inline functions (C++ functions).

Benefits of using macros: “Improved performance.” The defined identifier takes no memory and is a temporary symbol that will not exist after precompilation. Using macro definition with parameter in simple program can complete function call function, can reduce system overhead and improve operation efficiency. As in C, the use of functions makes programs more modular, easier to organize, and reusable. “Facilitate the modification of the program.” Use macro definitions to replace a constant that is often used in programs with macros. Note that it is used “often”. This way, when you need to change the value of this constant, you don’t need to change the entire program one by one. You just need to change the constant in the macro definition. When constants are long, macros can replace them with shorter, meaningful identifiers, making programming easier and less error-prone. Therefore, macro definitions have the advantage of being convenient and easy to maintain.

// Example: / find the volume of the ball#include<stdio.h>
#include<math.h>// For a sphere of radius R, V =4/3* π *r^3# define PI (3.14)

int main(void) {

	double r;
	scanf("%lf", &r); double sum = 0; Sum = (4.0/3.0) * PI*pow(r, 3); // PI is used instead of 3.14printf("%f.2", sum);

}

#includeint main(void) { enum week {Mon = 1, Tue, Wed, Thu, Fri, Sat, Sun}today; // Here we assign the value of Mon to 1, and the value of Tue and Tue to scanf("%d", &today);

	switch (today) {

	case Mon: puts("Monday"); break;
	case Tue: puts("Tuesday"); break;
	case Wed: puts("Wednesday"); break;
	case Thu: puts("Thursday"); break;
	case Fri: puts("Friday"); break;
	case Sat: puts("Saturday"); break;
	case Sun: puts("Sunday"); break;

	default: puts("no day"); 
	}

	return 0;

}
Copy the code

2. Enum Enumeration

An enumeration is a collection of named integer constants separated by commas. It is a user-defined data type. It is declared with the keyword enum in the following syntax: enum Enumerates the type name, {name 0… , name n}; The default value of the first enumerator is integer 0, and the value of subsequent enumerators is incremented by 1 (this can be customized, of course).

Enumeration type names are usually not really used. Instead, the names inside the braces are used, because they are constant symbols. They are of type int and have values from zero to n, such as enum week {Monday, Tuoday,Wedenday}; We create three constants, Monday with a value of 0, Tuoday with a value of 1, and Wedenday with a value of 2. The point of defining an enumeration is to give names to constants that need to be sorted. Although enumerations can be used as types, they are not really used very often. But if they are deliberately parallelized names, enumerations are more convenient than macros because they have ints. In C, enumerations are treated as int or unsigned int. Since enumerations are a data type, they can be declared as variables, just like primitive data types. Enumerations can also be aliases using the typedef keyword to define enumerated types and declare variables using that alias

Note: 1. The same program cannot define an enumeration type with the same name, and different enumeration types cannot have named constants with the same name

Enumerators are constants, not variables, so you cannot assign to them. You can only assign their values to other variables

3. The definition of enumerated types is separate from the declaration of variables: if an integer value is assigned to an enumerated variable, a type conversion is required

enum DAY { MON=1, TUE, WED, THU, FRI, SAT, SUN }; // The value of the enumeration constant is customizable here MON=1 // The assignment of the basic data type: int a, b, c; a = 1; b = 2; c = 3; // Use enumeration assignment: enum DAY yesterday, today, tomorrow; // enumerate the variable yesterday = MON; today = TUE; tomorrow = WED; // today = (enum DAY) (yesterday + 1); // cast tomorrow = (enum DAY) 30; // cast tomorrow = 3; / / errorCopy the code

Enumerations are handy to use with switch-case structures.

Type the number to see what day of the week it is#include 
      
       // Enumeration is a set instead of define
      

int main() { enum week { Mon = 1,Tues, Wed, Thurs, Fri, Sat, Sun } day; // week day; Define the scanf ("%d", &day);

	switch (day) {

	case Mon: puts("Monday"); break; / / 1 puts insteadprintfOutput stringcase Tues: puts("Tuesday"); break; / / 2case Wed: puts("Wednesday"); break; / / 3case Thurs: puts("Thursday"); break; / / 4case Fri: puts("Friday"); break; / / 5case Sat: puts("Saturday"); break; / / 6case Sun: puts("Sunday"); break; // 7 default: puts("Error!");

	}

	return 0;

}
Copy the code

Enumerations are an alternative to the #define preprocessor. Enumerations are very similar to macros. Macros replace names with values during preprocessing and enumerations replace names with values during compilation

3, struct structure

Struct is a structure, C programs often need to describe a data object with related different types of data. Describe the student’s comprehensive information, for example, students need to use the student id, name, the different types of data such as gender, as the data type is always together, so we might as well take these variables into the same folder, then use the key word struct statement said a data type is the use of the “folder”. Then it must be defined, that is, constructed, before it can be described and used. Just as a function must be defined before it can be specified or called. Structure is a collection, it contains more than one variable or array, they have the same type, can also be different, each such variable or array is known as a member of the structure, the structure is also a kind of data type, its own definition, by the programmer can contain multiple types of data, other members, also known as member variables, These are the basic structure types contained in a structure. They must be surrounded by “{}” and terminated with a semicolon. Each member should indicate a specific data type. A structure, like an array, is a collection of data that doesn’t make much sense as a whole. Arrays are accessed using subscripts [], and structures are accessed using dots. Access a single member. This way you can get the value of a member and assign a value to the member

Array: a [0] = 10; The members of a structure can contain Pointers to other structures and Pointers to its own structure type. These Pointers are usually used to implement more advanced data structures such as linked lists and trees.

Declaration definition structure:

Struct {struct}}; struct {struct}};

Struct week{define 1 struct week{define 2 struct week{define 3 int x; int x; int x; char y; char y; int y; }; }p1,p2; }p1,p2; Struct p1,p2; struct p1,p2; // there are X and y accesses in the same way. // declare the variables p1 and p2, which contain the values of week. // Declare the values of x and y. X // p1.y, p2.y For the first and third forms, both declare the structure name week, but the second type does not declare the structure name, but only defines two structure variables. This type is called nameless structure nameless structure: variables that can define nameless structure types. The compiler handles nameless structures by randomly generating a variable name that is not repeated. The way an unnamed structure is defined is that at least one variable of the type of the unnamed structure must be defined. Advantages: The neat thing about nameless structures is that they avoid double definitions of structures of the same type. In this way, you can define a structure for each queue of a specific type to manage the Pointers to the queue's head and tail. Even if you define multiple queues of the same specific type, you will not cause double definition compilation errors. This defines two queues with elements of type int, and each has a structure that maintains Pointers to the head and tail of the queue. The disadvantage is that we define an unnamed structure and declare three variables of that type. However, since there is no name, we cannot define a variable of the same type as those three variables after this sentence. Unless you define the same structure type again. Another important reason is that there is no way to define the structure variables we need in any other location. Every time we need to define a new structure variable, we have to find the location where the structure code was written in order to define the new structure. So we don't use nameless structures very often in real programmingCopy the code

Note: 1. The structure itself does not open up memory as data. What is stored in memory as data are the variables defined by the structure.

2, first declare struct type, then define variables of that type, declare struct type, do not allocate space to define struct type variables, allocate memory space

3. Use types that are less heavily used, such as short instead of int where possible, in order of the largest to smallest space occupied by the data type itself

P1 ={struct week}{5,10}; Equivalent to p1. X = 5, p1, y = 10; X =p2.x, y=p2.y; Struct variables cannot be added, subtracted, or multiplied or divided by each other, but struct variables can be assigned to each other. That is, one struct variable can be assigned to another struct variable. But only if the two struct variables have the same struct type

Struct operations: To access the entire structure, use the name of the structure variable directly. For the entire structure, you can do the assignment, take the address, or pass it to the function parameter

Structural value

A nested structure:

struct week{ int x; int y; strcut week at; // the struct defines a struct variable named at with the same parameter as week. X see.at.y}see; However, this is not recommended (or illegal), because this declaration is essentially an infinite loop, where the member at is a structure, and inside the AT there will be members of the structure, and so on, wireless loop. Struct week{int x; struct week{int x; struct week{int x; int y; strcut week *at; }see;}see;}see; But note the use of the -> operator see.at->x for pointer accessCopy the code

Structures reference each other:

A structure A contains one or more members related to structure B, and A structure B also contains one or more members related to structure A is called A cross-reference of A structure. If A member of structure A is not visible to A, then the compiler will report that the data type B is not defined.

strcut A; Strcut B; Strcut _A{strcut _B{int x; int x; int y; int y; struct _B a; struct _A b; (A.A.X B.B.X}A); (A.A.X B.B.X}A); (A.A.X B.B.X}A); (A.A.X B.B.X}A); B}; Strcut _A{strcut _B{int x; strcut _B{int x; strcut _A{strcut _B{int x; int x; int y; int y; struct _B *a; struct _A *b; // insert A pointer to A.a->x B.b->x}A; B}; Strcut _A{strcut _B{int x; strcut _B{int x; strcut _A{strcut _B{int x; int x; int y; int y; struct _B *a; struct _A *b; // insert A pointer to A.a->x B.b->x}A; B}; // At least one structure must be referenced as a pointer in another structure.Copy the code

Struct functions and function parameters

Struct takes function parameters:

The entire structure can be passed to a function as the value of an argument, in which case you create a new structure variable inside the function and copy the value of the caller’s structure, or you can return a value, which is completely different from an array where you pass a value as an argument to a structure variable, Pass the contents of the memory cell occupied by the structure variable (the list of structure variable members) to the parameter in order, where the parameter must also be a structure variable.

#include<stdio.h>typedef struct _node { int n; char a[100]; }NODE; void add(NODE a); Void main(void) {// To pass a structure, make a copy of the entire structure. scanf("%d %d", &t.a[0], &t.n); // Enter 1, 3printf("1-%d %d\n",t.a[0],t.n); // output 1 3 add(t);printf("3-%d %d\n", t.a[0], t.n); } void add(NODE a) {a.a[0] = 100;} void add(NODE a) {a.a[0] = 100; A.n = 666;printf("2-%d %d\n", a.a[0], a.n); // Output 100 666} ****// The solution is to use Pointers (which are often used) : ****#include<stdio.h>typedef struct _node { int n; char a[100]; }NODE; int add(NODE a); Void main(void) {// To pass a structure, make a copy of the entire structure. scanf("%d %d", &t.a[0], &t.n); // Enter 1, 3printf("1-%d %d\n",t.a[0],t.n); // output 1 3 add(&t); // This is the address of tprintf("3-%d %d\n", t.a[0], t.n); } int add(NODE *) {// define a structure pointer a.a[0] = 100; A.n = 666;printf("2-%d %d\n", a.a[0], a.n); // Output 100 666returna; } // Use a pointer to access the value called in the main functionCopy the code

Another way to do it

Struct does function:

/ * the above the first solution, into a structure function, then the function of operation, but there is no return back Problem is introduced to function outside the structure of the clones, rather than a pointer, the incoming structure and incoming array is different, the solution is in the input function, inside creates a temporary variable structure, This structure is then returned to the caller */#include<stdio.h>typedef struct _node { int x; int y; }NODE; struct _node add(); Int main(void) {NODE a; a.x = 0; a.y = 0;printf("1-%d %d\n", a.x, a.y); // 0 0 a = add(); // return n to aprintf("3-%d %d\n", a.x, a.y); // So the value has been changed at this pointreturn 0;
}

struct _node add() {

	NODE n;
	scanf("%d", &n.x); // Enter 1 3 scanf("%d", &n.y);

	printf("2-%d %d\n", n.x, n.y); // The assignment is successful in this casereturnn; } // This method can also achieve "change"", but often overhead memory is large, so the general case is more convenient to use PointersCopy the code

If the value of the parameter (which is also a structure variable) is changed during the execution of the called function, the value cannot be returned to the calling function. This is often inconvenient to use, so this method is rarely used.

Same as local variables. A structure declared inside a function can only be used inside a function, so it is common to declare a structure type outside a function so that it can be used by multiple functions

// struct do function argument examples (enter today to calculate tomorrow)#include<stdio.h>
#include
      
       // Use Boolean data types
      struct date { int year; int month; int day; }; bool If(struct date p); Int number(struct date c); Struct date (struct date today,tomorrow;printf("Year-month-day \ N");
	scanf("%d %d %d", &today.year, &today.month, &today.day); The last day of the month is the last day of the monthif(today.day==number(today)&&today.month! =1) {// day =1; tomorrow.month =today.month+1; tomorrow.year = today.year; }else if(today.day == number(today.month == 12) {// tomorrow.day = 1; tomorrow.month = 1; tomorrow.year =today.year+1; }else {
		tomorrow.day =today.day+1;
		tomorrow.month = today.month;
		tomorrow.year = today.year;
	}

	printf("Tomorrow is %d-%d-%d\n", tomorrow.year, tomorrow.month, tomorrow.day);
	return0; } struct date c (struct date c); 31,28,31,30,31,30,31,31,30,31,30,31 const int a [12] = {}; // Maximum number of days this monthif(c.month==22&&If(c)) {// Check If it is February and it is the year day = 29; // Is the year}else {

		day = a[c.month - 1];
	}

	returnday; } bool struct date p (struct date p) {// struct date p (struct date p) {// struct date p (struct date p)if(p.year % 4 == 0 && p.year / 100 ! = 0 || p.year % 400 == 0) {return true;
	}
	else {
		return false; }}Copy the code

// Struct do function example (calculate next second)#include<stdio.h>
struct time {
	int hour;
	int minute;
	int second;
};

struct time times(struct time now); // use structure to return value of function, Int main(void) {struct time nows[5] = {{11,50,20},{13,25,59},{12,59},{23,59,59},{00,00,00},}; int i;for (i = 0; i < 5; i++) {
		printf("Time is %d:%d:%d\n", nows[i].hour, nows[i].minute, nows[i].second);

		nows[i] = times(nows[i]);

		printf("Next second is %d:%d:%d\n", nows[i].hour, nows[i].minute, nows[i].second);
	}

	return 0;

}

struct time times(struct time now) {

	now.second++;
	if(now.second == 60) {//60 seconds now.minute++; now.second = 0;if(now.minute == 60)//60分 {now.hour++; now.minute = 0; now.second = 0;if(now.hour == 24) {// zero now.hour=0; now.minute = 0; now.second = 0; }}}returnnow; The return type must be the same as the function type, in other words, only the structure type can return the structure type}Copy the code

Struct array

Struct arrays, where each element in an exponential group is a struct. In practice, C language structure array is often used to represent a group with the same data structure, such as students in a class, workers in a workshop, etc. Structures can store different data types and relate them to each other. Struct arrays can store multiple structs consecutively, similar to arrays. For example, you want to define four coordinates of the same minimum enclosing rectangle and give the rectangle a feature number. When you need to store information about multiple minimum enclosing rectangles, you need to dynamically apply for an array of structures

To define a struct array, you do the same thing as defining a struct variable, but change the variable to an array. Struct student tp[10]; struct student tp[10]; This defines a struct array with 10 elements, each of which is a struct variable and contains all of the struct members.

The initialization of a structured array is the same as the initialization of a numeric array. The same methods and considerations apply to the initialization of a numeric array, because both arrays are arrays.

Example: // Find the student with the largest student number# include <stdio.h>
# include <string.h>struct STU { char name[20]; int age; char sex[20]; char num[20]; }; void OutputSTU(struct STU stu[]); Int main(void) {int I; struct STU stu[5];for (i = 0; i < 2; ++i)
	{
		printf("Please enter the information of student %d by name, age, sex, student number (1-9 digits) :", i + 1);

		scanf("%s %d %s %s", stu[i].name, &stu[i].age, stu[i].sex, stu[i].num); } OutputSTU(stu);} OutputSTU(stu);} OutputSTU(stu);return0; } void OutputSTU(struct STU stu[]) { struct STU stumax = stu[0]; // let the temporary structure stumax hold the information of the first student.for(j = 1; j < 2; ++j)// The first student in turn compares with the following students {if(stumax. Num, stu[J]. Num) < 0) // STCMP (stumax. Num, stu[J]. // Let temporary structure hold that student's information}}printf("Student Name: % S Student Age: % D Student Gender: % S Student Score: %s\n", stumax.name, stumax.age, stumax.sex, stumax.num);

}
Copy the code

Structure pointer

Unlike arrays, the name of a structure variable is not the address of the structure variable. The & operator strcut node *tp=&nb must be used. Pointers typically use -> to access members within a structure

Pointer variables are very flexible and can point to any type of variable. If we define a pointer variable to a structure-type variable, we can refer to the structure-type variable through a pointer.

#include<stdio.h>struct node{ int x; int y; }my; int main(void) { struct node *p = &my; // define a pointer p to my structure p->x = 11; // This is an access method (*p).x = 12; // This is the second way,printf("%d", p->x); The following two forms are equivalent: (* pointer variable). Member name. Pointer variable -> member name. The second of these is very important and is usually used. The other two are not used much. We're going to use the third way when we talk about linked lists.Copy the code

A structure is a data type. It is a template for creating variables. The compiler does not allocate memory for it, just as the keywords int, float, char do not occupy memory. Structure variables contain actual data and need memory to store them. So using a structure to take the address of a structure name is wrong, and you can’t assign it to any other variable.

#include<stdio.h>struct point { int x; int y; }; struct point *gt(struct point*p); // struct pointer function voidprint(const struct point *p); Void out(struct point p); Int main(void) {struct point y = {0,0}; // Gt is a pointer function to a structure gt(&y); // Take the address of y structure and pass in function out(y); out(*gt(&y)); *gt(&y) returns a pointer to this functionprint(gt(&y)); //gt(&y) is a return valueprint//*get(&y) = (struct point){1,2}; } struct point* gt(struct point*p) {"%d", &p->x);
	scanf("%d", &p->y);
	printf("a=%d,%d \n", p->x, p->y); // Use -> to access the members of the pointer structurereturnp; } void out(struct point p) {printf("b=%d,%d\n", p.x, p.y);
}

void print(const struct point *p) {// const struct point *pprintf("c=%d,%d\n", p->x, p->y);
}Copy the code
  • Pointer to array of structs:

    When we looked at numeric arrays, we could assign the name of the array to a pointer variable that pointed to the beginning of the array, and then use a pointer to access the elements of the array. Struct arrays are also arrays, so you can do the same.

We know that each element of a structure array is a structure variable. If you define a struct pointer variable and assign the name of the struct array to the pointer variable, you assign the address of the first element of the struct array, the address of the first member of the struct variable, to the pointer variable

# include <stdio.h>struct qt { char name[5]; int age; char sex[5]; double scroe; }; Int main(void) {struct qt student[5] = {{"李青", 20, "Male", 99}, {"Huang Huan", 20,  "Female", 80}, {"Groups", 23, "Male", 95}}; struct qt *p = student; int i;for (i = 0; i < 5; i++) {

		printf("%s ", p->name); // Utilize -> Accessible members (access means read and write)printf("%d ", p->age);
		printf("%s ", p->sex);
		printf("%f ", p->scroe);
	}
	return0; } When a struct pointer refers to an array of struct variables, the value of the pointer variable is the first address of the array, and the pointer variable p points to the first element of the array, student[0]. We know that when a pointer points to an array, the pointer can be moved to other elements of the array. The same applies to struct arrays and Pointers, so p + 1 points to the beginning of student[1]; P + 2 points to the first address of student[2]... So just useforThrough the loop, the Pointers point to the elements of the structure array one by one. Also note that to assign a struct array name to a struct pointer variable, they must have the same struct type.Copy the code

Typedef alias

Typedefs are used in programming languages to define simple aliases for complex declarations. New names are aliases for certain types, which improve program readability and are somewhat different from macro definitions. It is a key of a storage class and cannot be in the same expression as auto, extern, mutable, static, register, etc.

A typedef is a C keyword used to declare the new name of an existing data type, such as typedef int last. This makes last an alias for int so that the name last can be used instead of int in variable definitions and parameter declarations

A typedef also has a particular advantage: it conforms to the scope rule. A variable type defined using a typedef is limited in scope to the function or file defined (depending on where the variable is defined), whereas a macro definition does not.

There is a right-left rule for understanding complex declarations: starting with the name of a variable, go to the right, then to the left, and change direction when you hit a parenthesis. When parsed inside parentheses, exit parentheses, again right, then left, and so on, until the entire declaration is parsed. Example: int (*func)(int *p); Find the variable name func with a parentheses and an asterisk to the left, which means func is a pointer. (*func) is a function, so func is a pointer to a function that takes a parameter of type int and returns a value of type int. Int (* func [5]) (int *); To the right of func is the [] operator, indicating that func is an array of five elements. The * to the left of func indicates that the elements of func are Pointers. The element in the func array is a pointer to a function that takes a parameter of type int* and returns a value of type int. There are also two modes to remember:type(*) (...). A function pointertype(*)[] Array pointerCopy the code

Structure’s memory alignment (storage space)

Struct internal alignment: After a struct variable is defined, its memory storage is not equal to the sum of the widths of the elements it contains. The elements are placed in memory one by one in the defined order, but not in close order. Starting with the first address stored in the structure, when each element is placed into memory, it assumes that memory is divided by its own size, so the element placement must start at an integer multiple of its own width.

Memory alignment can greatly speed up memory access and is a way to trade space for time. Memory misalignment causes data to be read twice for each read, slowing down memory reads.

The CPU treats the memory as a block. The block size can be 2,4,8,16 bytes. Therefore, the CPU reads the memory piece by piece.

//2. Each member's initial address is an integer multiple of its own size // 3.#include<stdio.h>typedef struct _node { //char t; //1 //int p; / / / / 4floaty; //8 //char t = 0, t = 1 byte, int p = 1 at the next available address. Instead of a multiple of sizeof(int)=4, 3 bytes are needed to make the offset 4, so the system automatically fills 3 bytes to increase the offset to 4. Int p is placed there and takes up 4 bytes. The next available offset is 8, which satisfies sizeof(float) =4 alignment, sofloat//1+3+4+4=12 double a; //8 char b; //1 int c; //double a is stored at an offset of 0 and occupies 8 bytes. Char B is stored at an offset of 9 and occupies 1 byte. Int c to store the next available address at an offset of 9, 9 does not satisfy sizeof (int) =4; So the system will automatically allocate 3 bytes to increase to 12,12 meets alignment, and c takes up 4 bytes. //8+1+3+4=16}NODE; int main(void) {printf("%d ", sizeof(NODE));
}Copy the code

If there are elements larger than the number of processor bits in the structure, the aligned units are multiples of the processor. Otherwise, if the length of the elements in the structure is less than a multiple of the processor, the longest data element in the structure is used as the alignment unit.

And the memory address of a structure is the address of its first member variable isa is always the first member variable in a structure so the address of a structure is the address of its ISA pointer

  • Introduction to Memory Alignment

Since the reading time of memory is far less than the memory speed of CPU, we use the idea of setting the alignment coefficient of data structure, that is, sacrificing space for time to improve the memory efficiency of CPU.

Memory alignment should be the “domain” of the compiler. The compiler places each “data unit” in place in the program. But one of the things about C is that it’s so flexible and so powerful that it allows you to interfere with “memory alignment.” If you want to get to the bottom of the story, “memory alignment” shouldn’t be too obscure for you. This is also a problem with the small – and small-side patterns

Each compiler on a particular platform has its own default “alignment coefficient” (also known as the alignment modulus). Programmers can change this by using the precompiled command #pragma pack(n), where n is the “alignment factor” you want to specify.

Rules:

1. Alignment rules for data members: Data members of struct (or union), the first data member is placed at offset 0, and then each data member is aligned according to the value specified by #pragma Pack and the smaller of the length of the data member.

2. Overall alignment rules for structures (or unions) : After the data members have been individually aligned, the structures (or unions) themselves are aligned according to the value specified by #pragma Pack and the smaller of the maximum data member length of the structures (or unions).

If the n value of the #pragma pack is equal to or exceeds the length of all the data members, the size of the n value has no effect.

  • #pragma pack(n) sets variables to be aligned with n bytes:

    Role: Specifies struct, union, and class members

    Grammar: # pragma pack ([show] | [push | pop] [, identifier], n)

    1. Pack provides data-declaration-level control and has no effect on definitions;

    2. Pack will be called without an argument, and n will be set to the default;

    N: This parameter is optional. Specify the value of packing, in bytes; The default value is 8. Valid values are 1, 2, 4, 8, and 16. The other parameters are optional but not yet understood

#include<stdio.h>
# pragma pack (2) / / value can only fill in 1 2 4 August 16 it is best to see structure inside the smallest members here Here is the char so it is best to fill in 1 / / but when # pragma pack the value specified length is equal to or more than all of the data members, the size of the specified value will not produce any resultstypedef struct _A { double x; //4 int y; //4 char p; //1 }NODE; //8+4+1+1=14 Press n to make it 2. //8+4+1+3=16 Press N to make it more than 4 or use system automatic alignment#pragma pack(8)// Set to 4-byte alignment
typedef struct test{ char m1; double m4; int m3; }NODE2; / / 1 + 1 + 4 + 8 = 14 / / according to 2 / n / 1 + 7 + 8 + 4 = 20 no satisfaction in multiples of eight plus four equals 24 total: 1 + 7 + 8 + 4 + 4 = 24 int main (void) {printf("%d\n", sizeof(NODE));
	printf("%d", sizeof(NODE2)); } structure, union, or class data member, the first placed at offset 0; Subsequent alignment of each data member, as perPragma pack takes the smaller of the specified value and the length of the data member itself;In other words, whenWhen the value specified by #pragma pack equals or exceeds the length of all data members,The size of the specified value will have no effect;Copy the code

Each member is aligned separately, that is, each member is aligned in its own way and the length is minimized; The rule is that each member is aligned by the alignment parameter of its type (usually the size of the type) and the smaller of the specified alignment parameters.

The size of the end:

For example, int 11 22 33 44 Big end: 11 22 33 44 0 1 2 3 Low address ----> high address small end: 44 33 22 11 0 1 2 3 Low address ----> High address the difference is that the storage sequence is different. The common operating system is the small end, and the communication protocol is the big end.Copy the code
// Struct example: create a linked list using the tail insertion method#include
      
       // Create a single list
      typedef struct _node { int nb; Struct _node *nxte; // define a pointer to the next NODE}NODE; Typedef struct _link{// Use this struct to encapsulate the NODE *head; NODE *qt; }link; void add(link *phead, link *qt, int n); Int main(void) {link head, q; Head. Head = q.qt = NULL; // initialize int n;for (scanf("%d", &n); n != -1; scanf("%d", &n)) { add(&head, &q, n); } NODE *t; t = head.head; // Output the list using temporary structuresfor (; t; t = t->nxte) {
		printf("%d ", t->nb);
	}

	return0; Void add(link *phead, link *qt, int n) {NODE* p = (NODE*)malloc(sizeof(NODE)); P ->nb = n; p->nxte = NULL;if(phead->head == NULL) {phead->head = p; // the first node equals the new node}elseQt ->qt->nxte = p; } qt->qt = p; }Copy the code

4, The union

In the C programming language of some algorithms, it is necessary to store several different types of variables in the same memory unit. That is, using an overlay technique, several variables overlay each other. This structure, in which several different variables occupy a segment of memory together, is a data structure declared by the keyword union in C language, which is called “common body” type structure, also known as union.

“Union” has some similarities with “structure”. But there are fundamental differences. In a structure, each member has its own memory space. The total length of a structure variable is greater than or equal to the sum of the member lengths. In union, the members share a memory space, and the length of a union variable is equal to the longest length of each member. Note here refers to the so-called sharing is not put the multiple members at the same time into a joint variable, but to the members of the joint variables can be given any value, but every time can only be assigned a value, rushed into the new value is old values, Shared variables play a role of members is the last time a member of the store, after the deposit a new member, the original members of the lost, The address of a common variable is the same as the address of its members

  • A union type must be defined before a variable can be specified as the union type:

The general form for defining a union type is: union [name](union name) Name is optional {member list}; A member table contains several members. The general form of members is as follows: Type Specifier Member name Member names must be named according to identifiers. union Data { int i; double f; char str[20]; } data; Now all Data members share a single space, and only one member is valid ata time. Variables of Data type can store an integer, a floating-point number, or a string. This means that a variable (the same memory location) can store multiple types of data. You can use any of the built-in or user-defined data types in a common body as needed. The pool should occupy enough memory to store the largest members of the pool. For example, in the above example, Data would take up 20 bytes of memory space, because strings take up the most space among the individual members.Copy the code

Note: 1, the common variable cannot be used as a function argument, nor can the function back to the common variable, but can be used to specify a pointer to the common variable

2. All members occupy the same segment of memory. Modifying one member will affect all other members.

  • Pool access: Used when a pool accesses a member’s value. Operator, the -> operator for Pointers (same as for structs)

typedef union _node { int a; double b; char c; union _node *p; }NODE; int main(void) { NODE a; // define variable NODE t; a.b; // access t.p->a; // The use of the pointer -> access} union is almost the same as the use of the structure STRTCT, except for the internal representation. Addendum: There is also the nameless union, which works in the same way as the nameless structureCopy the code
#include
#include<string.h>typedef union _node{ int a; double b; char c[20]; }NODE; int main(void) { NODE a; // define only one variable a.a = 666;printf("%d\n", a.a); A. = 9.99;printf("%f\n", a.b);

	strcpy(a.c, "hello world!");
	printf("%s\n", a.c); // We see that all three are fully output, because only one member is valid at a time} output: 666 9.990000 hellow world!Copy the code
  • The role of common body:

    1, save memory, there are two very long data structures, will not be used at the same time, such as a representation of the teacher, a representation of the student, if you want to statistics of teachers and students with the structure of the words it is a bit of a waste! With structures, it takes up as much space as the longest data structure.

    2, the realization of conversion between different types of data, encountered a variety of types of data shared storage space, it is very convenient to achieve the conversion between different data types, do not need to display the forced type conversion.

    Others: 1. Determine the CPU mode: Determine the big-end and small-end modes

    For example, an int needs 4 bytes, while a char needs only 1 byte. The CPU mode can be determined based on the location of the 1 byte

    2, register definition, to achieve the overall access and single access

// Common synthesis example: output the required data according to the input data type#include<stdio.h>
#include
      
       // The data type output 5*4 m n n number of x
      union node { int a; double b; char c[30]; }add[10000]; char p[10000][30]; Int main(void) {int n, m; scanf("%d %d", &n, &m);
	int x;
	double y;
	char t[50];
	int i, j;

	for(i = 0; i < n; I++) {// enter scanf("%s", &p[i]); // As an array of strings, the address is requiredif (strcmp("INT", p[I]) == 0) {"%d", &x);
			add[i].a = x;
		}
		else if(strcmp("DOUBLE", p [I]) = = 0) {/ / float the scanf ("%lf", &y);
			add[i].b = y;
		}
		else if (strcmp("STRCING", p[I]) == 0) {"%s", t); strcpy(add[i].c, t); }}for(i = 0; i < m; I++) {// print scanf("%d", &j);

		if (strcmp("INT", p[j]) == 0) {
			printf("%d\n", add[j].a);
		}
		else if (strcmp("DOUBLE", p[j]) == 0)
		{
			printf("%f\n", add[j].b);
		}else if(strcmp("STRING",p[j])==0)
		{
			printf("%s\n", add[j].c); }}return0; } // Input: /* 5 4 INT 456 DOUBLE 123.56 DOUBLE 0.476 STRING welcomeToC STRING LemonTree 0 12 4 */ /* LemonTree */Copy the code