当前位置:网站首页>C language: five custom types
C language: five custom types
2022-06-13 09:13:00 【Caixinzhi】
Catalog
2. Self reference of structure
3. Structure variable definition and initialization
5. Change the default alignment number
5、 ... and 、 union ( Community )
One 、 Array
The first is the most common array , Arrays are also custom types , The previous article has introduced . Here is a detailed summary of the following four custom types .
Two 、 Structure
There can be different types of member variables stored in the structure .
1. Statement of structure
Structs can be declared in two ways : One is the general statement ; Second, special statement ( Also called incomplete declaration ).
1. Structure declaration
1.1 General statement
struct tag Structural tag
{
member_list; Store member list
}variable_list; Store variable list
1.2 Special statement / Incomplete declaration ( The output is the anonymous struct type )
struct
{
int a;
char b;
}x;
A general statement is a formal statement , It is also a kind that is used more ; And the special statement , That is to say, anonymous struct types will struct The following structure label is omitted , This also means that anonymous structs can only be used once after they are declared , Even two identical structure types , One of them holds pointer variables and points to another structure variable , Then put this pointer into something , It will also cause illegal access , Therefore, anonymous structure types are rarely used in actual code writing .
2. Self reference of structure
Error model 1:
struct Node
{
int data;
struct Node next;
};
Writing such code seems to be ok , It's a bit like recursion , But this is wrong , You cannot directly write one of the members in the structure as the same type as this structure , This will only cause an endless loop and crash the program , The correct changes are as follows :
struct Node
{
int data;
struct Node* next;
};
The structure should be struct Node Change the type to struct Node* type , This is similar to the linked list in the data structure , They are searched by the position pointed by the pointer .
If it's for use typedef What should we do to define the structure type to implement self reference ?
Error demonstration II :
typedef struct
{
int data;
Node* next;
}Node;
In reality, there will be many beginners' code like this , In fact, such code is incorrect . Although I noticed that I should use pointers to access , But because it uses typedef To define the , The code is declared at the end of the whole structure Node Of , So the middle part ( That is, inside the structure ) Of Node It's undefined . The correct modification should be as follows :
typedef struct Node
{
int data;
struct Node* next;
}Node;
Define the entire structure type as struct Node, The structure type pointer can be used inside the structure to call , Finally, I will make it clear that Node( That is, change the structure type to Node, To facilitate the following use of the call ).
3. Structure variable definition and initialization
In fact, this knowledge has been mentioned in previous articles , Relatively simple , Here's a little more sorting :
The structure definition is as follows :
struct Point
{
int x;
int y;
}p1;
struct Point p2;
One is to define variables while declaring types , Such as p1; The second is to define structural variables outside , Such as p2. Both definitions are global variables , If it is a structural variable defined in a function , Then the structural variable is local .
There are two most common types of structure initialization :
Initializing while defining structure variables , Such as :
struct Point
{
int x;
int y;
};
struct Point p = { 1,2 };
There is also a structure nested initialization , Like the following n1 and n2:
struct Point
{
int x;
int y;
};
struct Point p = { 1,2 };
struct Node
{
int data;
struct Point pp;
struct Node* next;
}n1 = { 10,{4,5},NULL };
struct Node n2 = { 20,{7,8},NULL };
4. Structure memory alignment
The first thing we need to be clear about is : The final goal after understanding the structure memory alignment is to be able to calculate the size of the structure .
Next is the structure alignment rule :
1. The first member of the structure , Stored at the beginning of the structure variable 0 Offset
2. Start with the second member , Must be aligned to the address of an integer multiple of the alignment number
Align numbers : The size of the member itself is compared with the default alignment number , Take the smaller value (VS A default alignment number for the environment is 8;Linux The environment does not have a default number of alignments -> The number of alignments is the size of the member itself )
3. The total size of the structure , Must be an integral multiple of the maximum number of alignments ( The maximum number of alignments is the largest of all members )
4. If the structure is nested , The nested structure is aligned to an integral multiple of its maximum alignment , The overall size of the structure is the maximum number of alignments ( The number of alignments with nested structures ) Integer multiple
At this time, many people have a question : Why is there memory alignment ?
1. Platform reasons ( Reasons for transplantation ): Not all hardware platforms can access any data on any address ; Some hardware platforms can only access certain types of data at certain addresses , Otherwise, hardware exceptions will occur .
2. Performance reasons : data structure ( Especially stacks ) It should be aligned as far as possible on the natural boundary . The reason lies in , To access unaligned memory ,CPU The processor needs to make two memory accesses ; The aligned memory access only needs one access .
in general : Memory alignment of structures is a way of trading space for time .
that , This method of trading space for time decreases with the running time , Sometimes a lot of space must be wasted . therefore , At this time, a method to design the structure that can not only meet the alignment but also save space is introduced , That is to make the members that occupy less memory gather together as much as possible . Skillfully use structural alignment rules , Insert some members that occupy little memory in the places where there is no content in the memory , It saves a lot of space . Take the following example :
struct s1
{
char c1;
int i;
char c2;
};
struct s2
{
char c1;
char c2;
int i;
};
These two structures s1 and s2 Type members are the same , But the alignment rules are used to calculate , You'll quickly find the structure s1 Its size is 12 byte , Struct s2 Its size is 8 byte , It has proved again that it can save space if the members occupying small memory are gathered together as much as possible .
5. Change the default alignment number
For modifying the default alignment number , have access to #pragma Preprocessing instructions .
for example :
1.
#pragma pack(6) // Set the default alignment number to 6
2.
#pragma pack() // Cancel the default alignment number , Restore to default
6. Structural parameters
Say first conclusion : When structures transmit parameters , To transfer the address of the structure .
So why ? Next, a simple code is used to explain .
struct S
{
int data[1000];
int num;
};
struct S s = { {1,2,3,4},1000 };
// Structural parameters
void print1(struct S s)
{
printf("%d\n", s.num);
}
// Structure address transfer parameter
void print2(struct S* s)
{
printf("%d\n", s->num);
}
int main()
{
print1(s); // Transmissive structure
print2(&s); // Address
}
about print1 Come on , Because when a function passes parameters , Parameters need to be stacked , There will be time and space overhead . that , In the long run , If you pass a structure object , The structure is too large , The system overhead of parameter stack pressing is relatively large , So it can lead to performance degradation .
And for print2 Come on , Because it passes the address , There is no such problem .
So in general , The first choice for structure parameter transmission is address transmission .
3、 ... and 、 Bit segment
What is a bit segment ?
In the final analysis, its bit segment is a special implementation of the structure , The declaration of bit segments and structs are similar , But there are two differences : The member of a bit segment must be int、unsigned int、char type ; Second, there is a colon and a number after the member name of the bit field .
You know what bit segments are , How does the bit segment allocate memory ? What are the noteworthy points ?
1. The space of the bit segment is based on 4 Bytes (int) perhaps 1 Bytes (char) The way to open up ( Easy to forget !!!)
2. The member of the bit segment should be an integer family (int, unsigned int, signed int, char)
3. Bit segments involve many uncertainties , The biggest difference between a bit segment and a structure is : Bit segments save memory space , But not across platforms , Therefore, programs that focus on portability should avoid using bit segments
Some points that should be paid attention to about bit segment cross platform problem :
1. int It's uncertain whether a bit segment is treated as a signed number or an unsigned number
2. The number of the largest bits in the bit segment cannot be determined (16 The biggest bit of machine is 16,32 The biggest bit of machine is 32, If the colon is followed by a number 25, stay 32 Bit machine span to 16 There will be problems when you are on the machine )
3. The members in the bit segment are allocated from left to right in memory , Or right to left allocation criteria have not yet been defined ( stay VS Environment is allocated from right to left )
4. When a structure contains two bit segments , The second segment is relatively large , Cannot hold the remaining bits of the first bit segment , Whether to discard the remaining bits or to use , This is uncertain ( stay VS Environment is abandoned )
summary : The bit segment is compared with the structure , Although it can achieve the same effect , It can also save more space than the structure , But there are cross platform problems .
For bit segments , Is cross platform really useless ? It's not , The following is an example of a bit segment implementation ( Data packets ):
When a packet passes data between two users , Yes, it will 4 Bit version number 、8 Bit service type 、8 Bit protocol is a series of things attached to the data to be sent , Form packets and transmit them together . Then you can imagine , Some only have 4 Bits if you use char Types are stored or some are 16 Bit by bit int When the type is stored , It will waste a lot of space , Then the transmission speed will be slow , So at this time, we will use bit segments to store these things , Save a space , The transmission efficiency can be improved .
Four 、 enumeration
enum Sex
{
MALE,
FEMALE,
SECRET
};
enum Color
{
RED,
GREEN,
BLUE
};
For example, the above two examples , Defined Sex and Color All belong to enumeration type . { } The contents in are possible values of enumeration types , Also known as enumeration constants .
among , These enumeration constants have values , The default is 0 Start , One increment 1, Of course, initial values can also be assigned when defining , Take the following example :
enum Color
{
RED=1,
GREEN=2,
BLUE=4
};
There are three other points worth noting :
1. The possible values stored in the enumeration type , Only one of them can be fetched at a time , Therefore, when calculating the size of the enumeration type, you will find that its size is just a int The size of the type
2. Enum types and struct types are defined in a similar way , All of them can be used typedef To define and declare
3. When assigning values to enumeration variables , It can only be assigned an enumeration constant ; If the enumeration variable is directly assigned with an integer , Will warn of type differences , Just like the following example :
#include <stdio.h>
typedef enum Color
{
RED=1,
GREEN=2,
BLUE=4
}Color;
int main()
{
Color clr = GREEN; // correct
//clr = 5; // error , There are type differences
printf("%d", clr);
return 0;
}
that , What are the advantages of using enumeration types ? You can't use all of them directly #define To define global variables ?
Here are a few advantages of enumerations :
1. Increase the readability and maintainability of the code
2. and #define The defined identifier comparison enumeration has type checking , More rigorous
3. Prevent named pollution ( encapsulation )
4. Easy to debug
5. Easy to use , You can define more than one constant at a time
5、 ... and 、 union ( Community )
Federation is also a special custom type , This type also contains a series of members , The most obvious feature is that these members share the same space ( Therefore, a consortium is also called a consortium ).
secondly , The size of the consortium also has its own calculation rules :
1. Members of a federation share a single memory space , The size of such a joint variable , At least the size of the largest member ( Because the Union has to be able to keep at least the largest member )
2. When the maximum member size is not an integral multiple of the maximum number of alignments , It's about aligning to an integer multiple of the maximum number of alignments
expand : Judge the size of the current machine
In fact, this problem has been done before , But the previous method is to cast the integer address to the character address , Then access the content of the address to determine whether it is equal to the original number , If equal , Small end byte order storage ; If not equal , Large end byte order storage .( If you don't know what the size side is, you can take a look at the previous article )
// Judge the big and small ends
#include <stdio.h>
// Method 1
int cheak_sys()
{
int a = 1;
if (*(char*)&a == 1)
{
return 1;
}
else
{
return 0;
}
}
// Method 2
int cheak_sys()
{
int a = 1;
return *(char*)&a;
}
int main()
{
int ret = cheak_sys();
if (ret == 1)
{
printf(" The small end \n");
}
else
{
printf(" Big end \n");
}
return 0;
}
Later, I learned that there is a library function :memcmp This library function compares memory , It is also possible to judge the size of the end .
But today we introduce a new method , This is a clever way to do it , It is the knowledge applied to the consortium :
#include <stdio.h>
int cheak_sys()
{
union Un
{
char c;
int i;
}u;
u.i = 1;
return u.c;
}
int main()
{
int ret = cheak_sys();
if (ret == 1)
{
printf(" The small end \n");
}
else
{
printf(" Big end \n");
}
return 0;
}
The subtlety of this consortium approach lies in the members of the consortium c and i Share a memory space , We first let the memory store i, because i yes int type , So it will open up 4 Bytes , Store it in a value , But we ended up just returning c( That is to say char type ), It only occupies one byte of memory in the same block of memory ( The first byte of the beginning ), You can judge whether it is a big end or a small end .
边栏推荐
- JUC原子引用与ABA问题
- Immutability of shared model
- 20211018 some special matrices
- QML compilation specification
- Some websites of QT (software download, help documents, etc.)
- Simulink如何添加模块到Library Browser
- QObject::connect: Cannot queue arguments of type ‘QTextCursor‘ (Make sure ‘QTextCursor‘ is registere
- Qvector shallow copy performance test
- Resolve importerror:lib*** so--cannot open shared object file: No such... (pycharm/clion reports an error but the shell does not)
- Opencv gaussianblur() explanation (Sigma value)
猜你喜欢
教程篇(5.0) 02. 管理 * FortiEDR * Fortinet 网络安全专家 NSE 5
How Simulink adds modules to the library browser
The Jenkins console does not output custom shell execution logs
C language: deep understanding of pointers and arrays
20220524 如何把CoppeliaSim安装到D盘
Yolov5 face learning notes
Collection of garbled code problems in idea development environment
Installation of sonarqube code quality management platform (to be continued)
JUC 原子累加器 源码之 LongAdder
20211104 为什么相似矩阵的迹相同
随机推荐
JUC原子整数
Longadder of the source code of JUC atomic accumulator
教程篇(5.0) 03. 安全策略 * FortiEDR * Fortinet 网络安全专家 NSE 5
Yolov5 model evaluation
Library management system based on wechat applet Rar (thesis + source code)
C language: Simulated Implementation of library function strcpy
20211018 some special matrices
C/S模型与P2P模型
202012 CCF test questions
20211104 why are the traces of similar matrices the same
Lecture par lots de tous les fichiers vocaux sous le dossier
20220524 how to install coppeliasim to disk D
MySQL startup error: innodb: operating system error number 13 in a file operation
LeetCode 剑指 Offer 30. 包含min函数的栈
Installation of sonarqube code quality management platform (to be continued)
JUC 原子累加器 源码之 LongAdder
Module build failed: TypeError: this. getOptions is not a function at Object. stylusLoader
QML(06)——qml. Add a new folder under QRC
Mttr/mttf/mtbf diagram
Cmake Learning Series I