当前位置:网站首页>The use of char[0] and char[1] in C language structure
The use of char[0] and char[1] in C language structure
2022-06-24 03:52:00 【Good pie notes】
1. Write it at the front
I'm doing it Linux 64 Bit driver compatible 32 Bit application adaptation process , I deeply feel the trouble caused by pointer operation , Especially in the application layer 32 After the bit pointer is passed to the kernel layer , The pointer size becomes 64 position , Frequent resizing is required , It's very uncomfortable . When I'm about to finish all my work , Listen to a colleague say you can use char[0] Use instead of pointer , I almost got a mouthful of old blood .“ Why didn't you say …”. Next, from the Internet google, Discover the subtlety of this usage , Close up this article , To take notes . (PS: I still want to thank my colleague YYL, Let me again get To a skill ^_^)
Add... At the end of the structure char[0] or char[1] The usage of is GNU C An extension of , stay ISO/IEC 9899-1999 Inside , It's illegal to write that . This is used in C99 called Flexible array . A flexible array member must be preceded by at least one other type member . Structures that contain flexible array members should use malloc Dynamic memory allocation , And the allocated memory should be larger than the size of the structure , To fit the expected size of the flexible array .
2. The purpose of quoting this usage
The main purpose is to facilitate the management of memory buffers , If you use pointers directly instead of arrays , that , When you allocate a memory buffer , You must assign the structure once , Then redistribute the pointer in the structure once ,( At this time, the allocated memory is not continuous with the memory of the structure , Therefore, it is necessary to manage separately, that is, application and release ) And if you use an array , Then it only takes one time to allocate them all , In turn, , The same is true when released , Using arrays , One release , Use the pointer , You have to release the pointer in the structure first , Re release structure . You can't reverse the order yet .
In fact, it is to allocate a continuous section of memory , Reduce memory fragmentation .
3. usage
Copy
1 2 3 4 5 6 7 | struct Msg { ... // Other members ... // Other members int nLen; // commonly char data[0] Will be preceded by a length nLen Express data Size char data[0]; // char[0] or char[1] It has to be at the end }; |
|---|
One thing we need to know is :char data[0] This array has no elements , Its address is followed by nLen After the address , If the allocated memory is larger than the actual size of the structure , So the big part is data The content of .
In actual use , It's usually used this way
Copy
1 2 3 | int dataBytes = 10; // It is specified here that data The data size of struct Msg *p = (struct Msg *)malloc(sizeof(struct Msg) + dataBytes); // Dynamic allocation p->nLen = dataBytes; // Assign the length to nLen, To facilitate other parts to use this structure |
|---|
If you don't understand , A string of codes , At a glance :
Copy
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 | // test.c #include <stdio.h> #include <string.h> typedef struct body1 { int a; int b; }__attribute ((packed)) BODY1; //__attribute ((packed)) Is to force no byte alignment typedef struct body2 { int len; char *data; }__attribute ((packed)) BODY2; typedef struct body3 { int len; char data[0]; }__attribute ((packed)) BODY3; typedef struct body4 { int len; char data[1]; }__attribute ((packed)) BODY4; int main() { BODY1 b1; BODY2 b2; BODY3 b3; BODY4 b4; memset(&b1, 0, sizeof(BODY1)); memset(&b2, 0, sizeof(BODY2)); memset(&b3, 0, sizeof(BODY3)); memset(&b4, 0, sizeof(BODY4)); printf("sizeof(b1) = %ld\n", sizeof(b1)); printf("sizeof(b2) = %ld\n", sizeof(b2)); printf("sizeof(b3) = %ld\n", sizeof(b3)); printf("sizeof(b4) = %ld\n", sizeof(b4)); printf(" b2 addr = %p\n", &b2); printf("b2.data addr = %p\n", b2.data); printf(" b3 addr = %p\n", &b3); printf("b3.data addr = %p\n", b3.data); printf(" b4 addr = %p\n", &b4); printf("b4.data addr = %p\n", b4.data); return 0; } |
|---|
The procedure is in 64 Compile under bit system , The operation results are as follows :
Copy
1 2 3 4 5 6 7 8 9 10 | sizeof(b1) = 8 sizeof(b2) = 12 sizeof(b3) = 4 sizeof(b4) = 5 b2 addr = 0x7ffded4f3633 b2.data addr = (nil) b3 addr = 0x7ffded4f363f b3.data addr = 0x7ffded4f3643 b4 addr = 0x7ffded4f3643 b4.data addr = 0x7ffded4f3647 |
|---|
As can be seen from the above results :
- char data[0] It doesn't take up any space , and char *data Occupied the size of a pointer variable , Never put char data[0] As a pointer , It is actually an offset , This offset points to the space immediately behind the structure .
- char[1] It takes up space , If you do not force byte alignment , Then the size of the structure will be 8.char[0] and char[1] The effect is the same .
- b3 Of data Address , yes b3 The address at the beginning of the structure plus len Occupied by 4 Address of byte ,b4 Is the same .
4. With pointer and char[0] The difference between
- Use pointers in structures : Creation time , The system first allocates memory for the structure , Reallocate the pointer to data Of memory . Two pieces of memory are not continuous . When released , Free the memory pointed to by the pointer first , Then release the structure memory .
- Used in structures char[0]: Creation time , The system allocates the memory of the structure and data Of memory , The two pieces of memory are contiguous ( More specifically, a block of memory ). When released , One time release .
============================================================
In everyday programming , Sometimes you need to store a dynamic length string in the structure , General practice , Is to define a pointer member in the structure , This pointer member points to the dynamic memory space where the string is located , for example :
123456 | typedef struct test{int a;double b;char *p;}; |
|---|
p Point to string . This method causes the string to be separated from the structure , Not conducive to operation . If you concatenate a string directly with a structure , Isn't it better ? therefore , You can change the code to this :
123 | char a[] = "hello world";test *stpTest = (test *)malloc(sizeof(test) + strlen( a ) + 1 );strcpy(stpTest + 1, a ); |
|---|
thus ,( char* )(stpTest + 1 ) It's just a string "hello world" The address of the . Now p Become superfluous , Can be removed . however , Another problem arises : Always use ( char* )((stpTest + 1 ) inconvenient . If you can find a way , This string can be referenced directly , Without occupying the space of the structure , It's perfect , The code structure that meets this condition should be a non object symbolic address , Place a at the end of the structure 0 An array of lengths is a wonderful solution . however ,C/C++ The standard cannot define the length as 0 Array of , therefore , Some compilers put 0 Length of the array members as their own Nonstandard extensions .
Before we talk about flexible array members , First, I want to introduce incomplete types (incomplete type). An incomplete type is a type , It lacks enough information, such as length, to describe a complete object ,
Its appearance reflects C Programmers' ultimate pursuit of refining code , This code structure arises from the need for dynamic structures .
In view of the important role of this code structure ,C99 Even included it in the standard .C99 Use incomplete types to implement flexible array members , stay C99 in , The last element in the structure is allowed to be an array of unknown size , This is called a flexible array (flexible array) member ( Also called scalable array members ), But a flexible array member in a structure must be preceded by at least one other member . Flexible array members allow structures to contain an array of variable size . A flexible array member exists only as a symbolic address , And it has to be the last member of the structure ,sizeof The size of the structure returned does not include the memory of the flexible array . Flexible array members can be used not only for character arrays , It can also be arrays with other types of elements . Structures that contain flexible array members use malloc () Function to dynamically allocate memory , And the allocated memory should be larger than the size of the structure , To fit the expected size of the flexible array . See the following example for the use of flexible arrays :
123456 | typedef struct test{int a;double b;char c[0];}; |
|---|
Some compilers will report errors and cannot compile. They can be changed to :
123456 | typedef struct test{int a;double b;char c[];}; |
|---|
Allocate memory to the structure through the following expression :
1 | test *stpTest = (test *)malloc(sizeof(test)+100*sizeof(char)); |
|---|
c Is a flexible array member , If you put stpTest The dynamically allocated memory pointed to is considered as a whole ,c Is a structure member whose length can change dynamically , The word "flexibility" comes from this .c The length of is 0, So it doesn't take up test Space , meanwhile stpTest->c Namely “hello world” The first address , No need to use ( char * )( stpTest + 1 ) Such ugly code . that 0 An array of elements doesn't take up space , Then we can do the lengthening operation . So we give the structure pointer c Allocated a block of memory . use stpTest->c[n] You can simply access variable length elements .
Of course , Since the top is used malloc Function allocates memory , Definitely need to use free Function to free memory :
1 | free(stpTest); |
|---|
Standard forms should be used wherever possible , In Africa C99 The occasion of , You can use the pointer method . It should be noted that :C89 I don't support this kind of thing ,C99 Add it to the standard as a special case . however ,C99 What is supported is that incomplete type, instead of zero array, It's the same int a[0]; This form is illegal ,C99 The form of support is in the form of int a[]; It's just that some compilers put int a[0]; As Nonstandard extensions To support , And in C99 There was this nonstandard extension before the release ,C99 After the release , Some compilers combine the two .
Because the array has no elements , The array allocates space in the structure , therefore sizeof(struct Mydata) = 4. malloc The application is 14 Bytes of contiguous space , It returns a pointer to this 14 Bytes , Cast to struct INFO When , front 4 Bytes are considered Mydata structure , The latter part is copied “123456789” The content of .
3、 In practice
In practice , The length of data is unknown , In this way, the space can be saved by changing the length of the array . Operate on pointer , Convenient data type conversion . The test procedure is as follows :
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <string.h>
4 #include <stdint.h>
5
6 typedef struct
7 {
8 int data_len;
9 char data[0];
10 }buff_st_1;
11
12 typedef struct
13 {
14 int data_len;
15 char *data;
16 }buff_st_2;
17
18 typedef struct
19 {
20 int data_len;
21 char data[];
22 }buff_st_3;
23
24 typedef struct
25 {
26 uint32_t id;
27 uint32_t age;
28 }student_st;
29
30
31 void print_stu(const student_st *stu)
32 {
33 printf("id:%u,age:%u\n", stu->id, stu->age);
34 }
35
36 int main()
37 {
38 student_st *stu = (student_st *)malloc(sizeof(student_st));
39 stu->id = 100;
40 stu->age = 23;
41
42 student_st *tmp = NULL;
43
44 buff_st_1 *buff1 = (buff_st_1 *)malloc(sizeof(buff_st_1) + sizeof(student_st));
45 buff1->data_len = sizeof(student_st);
46 memcpy(buff1->data, stu, buff1->data_len);
47 printf("buff1 address:%p,buff1->data_len address:%p,buff1->data address:%p\n",
48 buff1, &(buff1->data_len), buff1->data);
49
50 tmp = (student_st*)buff1->data;
51 print_stu(tmp);
52
53 buff_st_2 *buff2 = (buff_st_2 *)malloc(sizeof(buff_st_2));
54 buff2->data_len = sizeof(student_st);
55 buff2->data = (char *)malloc(buff2->data_len);
56 memcpy(buff2->data, stu, buff2->data_len);
57 printf("buff2 address:%p,buff2->data_len address:%p,buff2->data address:%p\n",
58 buff2, &(buff2->data_len), buff2->data);
59
60 tmp = (student_st *)buff2->data;
61 print_stu(tmp);
62
63 buff_st_3 *buff3 = (buff_st_3 *)malloc(sizeof(buff_st_3) + sizeof(student_st));
64 buff3->data_len = sizeof(student_st);
65 memcpy(buff3->data, stu, buff3->data_len);
66 printf("buff3 address:%p,buff3->data_len address:%p,buff3->data address:%p\n",
67 buff3, &(buff3->data_len), buff3->data);
68
69 tmp = (student_st*)buff1->data;
70 print_stu(tmp);
71
72 free(buff1);
73
74 free(buff2->data);
75 free(buff2);
76
77 free(buff3);
78 free(stu);
79 return 0;
80 }use char *data, Secondary allocation is required , The operation is more troublesome , It's easy to cause memory leaks . Instead, use variable length arrays directly , It just needs to be allocated once , Then you can take the value .
边栏推荐
- 内存泄漏之KOOM
- 在pycharm中pytorch的安装
- Summary of rust high concurrency programming
- Do you understand TLS protocol?
- Use the fluxbox desktop as your window manager
- Recording a summary of frequently asked questions
- Tencent cloud ASR product -php realizes the authentication request of the extremely fast version of recording file identification
- TCP three handshakes and four waves
- How to gracefully handle and return errors in go (1) -- error handling inside functions
- An open source monitoring data collector that can monitor everything
猜你喜欢

你了解TLS协议吗?

Modstartcms enterprise content site building system (supporting laravel9) v4.2.0

Brief ideas and simple cases of JVM tuning - how to tune

内存泄漏之KOOM

Idea 1 of SQL injection bypassing the security dog

On game safety (I)

Clickhouse (02) Clickhouse architecture design introduction overview and Clickhouse data slicing design

【代码随想录-动态规划】T392.判断子序列

flutter系列之:flutter中的offstage

halcon知识:区域(Region)上的轮廓算子(2)
随机推荐
NLP task summary introduction and understanding
A problem of testing security group access in windows10
Old popup explorer Exe has stopped working due to problems. What should I do?
Received status code 502 from server: Bad Gateway
Several key tools for cloud native implementation
Ar 3D map technology
一次 MySQL 误操作导致的事故,「高可用」都顶不住了!
Do you understand TLS protocol?
After 20 years of development, is im still standing still?
The request was aborted: Could not create SSL/TLS secure channel.
How to avoid man in the middle attack (mitm)
Independent innovation and localization technology: SMT production line monitoring and management visualization of intelligent manufacturing
Use the fluxbox desktop as your window manager
What does elastic scaling of cloud computing mean? What are the application scenarios for elastic scaling of cloud computing?
Some basic knowledge of data center server cabinet
Record the creation process of a joke widget (I)
web渗透测试----5、暴力破解漏洞--(1)SSH密码破解
Grpc: how to add API log interceptors / Middleware?
Use lightweight application server to automatically download and upload to onedrive
ModStartCMS 企业内容建站系统(支持 Laravel9)v4.2.0