Custom types: structure, enumeration, union

Directory:

Table of contents:

Structure

Declaration of structure type

self-referencing of structures

Definition and initialization of structure variables

Structure memory alignment

Structure parameter passing

Structure implements bit fields (filling of bit fields & portability)

enumerate

Definition of enumeration type

Advantages of enumerations

Use of enumerations

joint

union type definition

Features of the union

Union size calculation


1. Structure:

A structure is a collection of values called member variables. Each member of the structure can be a variable of different types.

2. Declaration of structure type:

struct Stu
{
 char name[20];//name
 int age;//Age
 char sex[5];//Gender
 char id[20];//student number
}; //The semicolon cannot be lost

2.1 Special statement:

//Anonymous structure type
struct
{
 int a;
 char b;
 float c;
}x;
struct
{
 int a;
 char b;
 float c;
}a[20], *p;

The above two structures omit the structure tag when declaring (
tag
).

So here’s the problem?

//
Based on the above code, is the following code legal?

p
=&
x
;

Warning:

The compiler will treat the two declarations above as two completely different types.

So it’s illegal.

3. Self-reference of structure:

Is it okay to include a member in a structure that is of type the structure itself?

//Code 1
struct Node
{
 int data;
 struct Node next;
};
//Is it possible?
If so, what is sizeof(struct Node)? 

Correct way to self-reference:

//Code 2
struct Node
{
 int data;
 struct Node* next;
};

//Code 3
typedef struct
{
 int data;
 Node* next;
}Node;
//Is it possible to write code like this?
//solution:
typedef struct Node
{
 int data;
 struct Node* next;
}Node;

4. Definition and initialization of structure variables:

With the structure type, how to define variables is actually very simple.

struct Point
{
 int x;
 int y;
}p1; //Declare the type and define variable p1 at the same time
struct Point p2; //Define structure variable p2
//Initialization: Define variables and assign initial values at the same time.
struct Point p3 = {x, y};
struct Stu //Type declaration
{
 char name[15];//name
 int age; //Age
};
struct Stu s = {"zhangsan", 20};//Initialization
struct Node
{
 int data;
 struct Point p;
 struct Node* next;
}n1 = {10, {4,5}, NULL}; // Nested initialization of structure
struct Node n2 = {20, {5, 6}, NULL}; // Nested initialization of structure

5. Structure memory alignment:

We have mastered the basic use of structures.

Now let’s delve into a problem: calculating the size of a structure.

This is also a particularly popular test site:
Structure memory alignment

//Exercise 1
struct S1
{
 char c1;
 int i;
 char c2;
};
printf("%d\
", sizeof(struct S1));
//Exercise 2
struct S2
{
 char c1;
 char c2;
 int i;
};
printf("%d\
", sizeof(struct S2));
//Exercise 3
struct S3
{
 double d;
 char c;
 int i;
};
printf("%d\
", sizeof(struct S3));
//Exercise 4-structure nesting problem
struct S4
{
 char c1;
 struct S3 s3;
 double d;
};
printf("%d\
", sizeof(struct S4));

Test center

How to calculate
?

First, you must master the alignment rules of structures:

1.
The offset of the first member from the structure variable is
0
address.

2.
Other member variables should be aligned to addresses that are integer multiples of a certain number (alignment number).

Number of alignments
=
The compiler defaults an alignment number equal to the size of the member
Smaller value
.

VS
The default value in
8

3.
The total size of the structure is an integer multiple of the maximum alignment number (each member variable has an alignment number).

4.
If a structure is nested, the nested structure is aligned to an integer multiple of its own maximum alignment number, and the entire length of the structure is

The body size is an integer multiple of the maximum alignment number (including the alignment number of nested structures).

Why memory alignment exists
?

Most of the reference materials say this:

1.
Platform reasons
(
Reason for transplantation
)
:

Not all hardware platforms can access any data at any address; some hardware platforms can only access certain special data at certain addresses.

data of a certain type, otherwise a hardware exception is thrown.

2.
Performance reasons
:

data structure
(
Especially the stack
)
Should be aligned on natural boundaries as much as possible.

The reason is that in order to access unaligned memory, the processor needs to make two memory accesses; aligned memory access requires only one access.

ask.

In general:

The memory alignment of the structure is
Space
in exchange for
Time
way of doing.

When designing a structure, we must not only satisfy alignment but also save space. How to do this:

Let members who take up less space gather together as much as possible

//For example:
struct S1
{
 char c1;
 int i;
 char c2;
};
struct S2
{
 char c1;
 char c2;
 int i;
};

6. Modify the default alignment number:

we’ve met before
#pragma
This preprocessing directive, which we use again here, changes our default alignment number.

#include <stdio.h>
#pragma pack(8)//Set the default alignment number to 8
struct S1
{
 char c1;
 int i;
 char c2;
};
#pragma pack()//Cancel the set default alignment number and restore it to the default
#pragma pack(1)//Set the default alignment number to 1
struct S2
{
 char c1;
 int i;
 char c2;
};
#pragma pack()//Cancel the set default alignment number and restore it to the default
int main()
{
    //What is the output result?
    printf("%d\
", sizeof(struct S1));
    printf("%d\
", sizeof(struct S2));

Conclusion:

When the alignment of the structure is inappropriate, can we change the default alignment number ourselves?

7. Structure parameter passing:

struct S
{
 int data[1000];
 int num;
};
struct S s = {<!-- -->{1,2,3,4}, 1000};
//Structure passing parameters
void print1(struct S s)
{
 printf("%d\
", s.num);
}
//Structure address passing parameters
void print2(struct S* ps)
{
 printf("%d\
", ps->num);
}
int main()
{
 print1(s); //Pass structure
 print2( & amp;s); // Pass address
 return 0;
}

above
print1
and
print2
Which function is better?

The answer is: preferred
print2
function.

reason:

When a function passes parameters, the parameters need to be pushed onto the stack, which will cause system overhead in time and space.

If a structure object is passed and the structure is too large, the system overhead of pushing parameters onto the stack will be relatively large, which will lead to performance degradation.

decline.

8. Structure implements bit fields (filling & portability of bit fields) ):

What is a bit segment

The declaration and structure of bit fields are similar, with two differences:

1.
Members of the rank must be
int
,
unsigned int
or
signed int
.

2.
The member name of the bit field is followed by a colon and a number.

struct A
{
 int _a:2;
 int _b:5;
 int _c:10;
 int _d:30;
};

Memory allocation for 8.1-bit segment:

1. The members of the bit field can be int unsigned int signed int or char (belonging to the integer family) type

2.
The space of the bit segment is based on the need
4
bytes (
int
)or
1
bytes (
char
) way to develop.

3.
Bit segments involve many uncertainties. Bit segments are not cross-platform. Programs that focus on portability should avoid using bit segments.

//An example
struct S
{
 char a:3;
 char b:4;
 char c:5;
 chard:4;
};
struct S s = {0};
s.a = 10;
s.b = 12;
s.c = 3;
s.d = 4;
//How is space opened up? 

Cross-platform issues in the 8.2-bit segment:

1. int
It is undefined whether a bit field is treated as a signed or unsigned number.

2.
The maximum number of bits in a bit field cannot be determined. (
16
Bit machine maximum
16
,
32
Bit machine maximum
32
, written as
27
,exist
16
bit machine

There will be problems with the machine.

3.
The criteria for whether members of a bit field are allocated from left to right or right to left in memory are undefined.

4.
When a structure contains two bit fields, and the members of the second bit field are larger and cannot fit in the remaining bits of the first bit field, it is

It is uncertain whether to discard the remaining bits or to use them.

Summary:

Compared with the structure, the bit segment can achieve the same effect, but can save space very well, but there are cross-platform problems.

9. Enumeration:

Enumeration, as the name suggests, means enumerating items one by one.

List the possible values one by one.

For example, in our real life:

Monday to Sunday of the week is limited
7
God, you can list them all.

10. Definition of enumeration type:

enum Day//week
{
 Mon,
 Tues,
 Wed,
 Thur,
 Fri,
 Sat,
 Sun
};
enum Sex//gender
{
 MALE,
 FEMALE,
 SECRET
};
enum Color//color
{
 RED,
 GREEN,
 BLUE
};

defined above
enum Day
,
enum Sex
,
enum Color
All are enumeration types.

{}
The content in is the possible values of the enumeration type, also called
enum constants
.

These possible values are all valid, and the default is from
0
Start, increment once
1
, of course, you can also assign an initial value when defining.

11. Advantages of enumeration:

we can use
#define
To define constants, why do we have to use enumerations?

Advantages of enumerations:

1.
Increase code readability and maintainability

2.
and
#define
Defined identifiers have type checking and are more rigorous than enumerations.

3.
Prevented naming pollution (encapsulation)

4.
Easy to debug

5.
Easy to use, multiple constants can be defined at one time

12.United:

Union is also a special custom type

Variables defined in this type also contain a series of members. The characteristic is that these members share the same space (so a union is also called a union).

for example

13. Definition of union type:

//Declaration of union type
union Un
{
 char c;
 int i;
};
//Definition of joint variables
union Un un;
//Calculate the size of two variables
printf("%d\
", sizeof(un))

14. Characteristics of Union:

The members of a union share the same memory space, so the size of a union variable is at least the size of the largest member (because the union variable

The union must at least be able to save the largest member

union Un
{
 int i;
 char c;
};
union Un un;
//Are the results output below the same?
printf("%d\
", & amp;(un.i));
printf("%d\
", & amp;(un.c));
//What is the result output below?
un.i = 0x11223344;
un.c = 0x55;
printf("%x\
", un.i);

15. Calculation of union size:

The size of the union is at least the size of the largest member.

When the maximum member size is not an integer multiple of the maximum alignment number, it must be aligned to an integer multiple of the maximum alignment number.

union Un1
{
 char c[5];
 int i;
};
union Un2
{
 short c[7];
 int i;
};
//What is the result output below?
printf("%d\
", sizeof(union Un1));
printf("%d\
", sizeof(union Un2));