在一些 C 语言编写的代码中,有时可以看到如下定义的结构:
view plaincopy to clipboardprint?
1. typedef struct user_def
2. {
3. char * name;
4. int length;
5. char bytes[0];
6. } user_def_t;
typedef struct user_def { char * name; int length; char bytes[0]; } user_def_t;
这个 bytes 是什么意思?我们知道 0 == sizeof(bytes),那么 bytes 仅仅是为了定义结构的尾地址吗?
不是的。这里的 bytes 是作为扩展数组用的。请看如下代码:
view plaincopy to clipboardprint?
1. int alloc_user_def_t(user_def_t * p, int length)
2. {
3. p = (user_def_t)malloc(sizeof(user_def_t) + length);
4. if (NULL == p)
5. {
6. return -1;
7. }
8.
9. p->name = NULL;
10. p->length = length;
11. memset(p->bytes, 0, length);
12. return 0;
13. }
int alloc_user_def_t(user_def_t * p, int length) { p = (user_def_t)malloc(sizeof(user_def_t) + length); if (NULL == p) { return -1; } p->name = NULL; p->length = length; memset(p->bytes, 0, length); return 0; }
是不是很酷?同样,也可以把 name 域的值附在结构后面:
view plaincopy to clipboardprint?
1. int alloc_user_def_t(user_def_t * p, char * name, int length)
2. {
3. p = (user_def_t)malloc(sizeof(user_def_t) + strlen(name) + length + 1);
4. if (NULL == p)
5. {
6. return -1;
7. } p->name = p + sizeof(user_def_t) + length;
8. memcpy(p->name, name, strlen(name) + 1); /* 别忘了'\0' */
9. p->length = length;
10. memset(p->bytes, 0, length);
11. return 0;
12. }
int alloc_user_def_t(user_def_t * p, char * name, int length) { p = (user_def_t)malloc(sizeof(user_def_t) + strlen(name) + length + 1); if (NULL == p) { return -1; } p->name = p + sizeof(user_def_t) + length; memcpy(p->name, name, strlen(name) + 1); /* 别忘了'\0' */ p->length = length; memset(p->bytes, 0, length); return 0; }
总结:在某一结构末尾如定义类似 char bytes[0] 的零长数组,表示该结构不定长,可通过数组的方式进行扩展。结构中必包含一个长度信息。结构本身类似于一个信息头。同时,此结构只能通过堆方式分配内存。
PS:注意在用malloc分配空间时要分配数组的空间,不然会出现溢出!
分享到:
相关推荐
在C语言中,结构体零长度数组是一种特殊的技巧,它允许结构体的大小在运行时动态扩展。这种技术并不是所有C标准都支持的,但在GNU C编译器中是允许的,而在ANSI C和C++中则不被支持。在结构体中定义一个零长度数组,...
结构体零长度数组的意义(深入) 在 Linux 系统中,结构体最后的长度为 0 或者 1 的数组是一个非常重要的概念。这在 /usr/include/linux/if_pppox.h 里面有一个结构体的定义,名为 struct pppoe_tag: ```c struct ...
在某些情况下,我们可能需要创建包含可变长度数据的结构体,这时可以使用"结构体中最后一个数组长度为零"的技术。这个技术常用于表示如TLV(Type-Length-Value)格式的数据,其中长度可以根据需要变化。 在提供的...
在这个例子中,我们定义了一个 _CAPI_Point3d 结构体数组,数组长度为 count。 Marshal 类 在 C# 中,Marshal 类是用于在托管代码和非托管代码之间进行数据类型转换的。例如,在本例中,我们使用 Marshal....
此外,C#中数组的大小并非其类型的一部分,这意味着在声明数组后,可以对其赋值不同长度的数组,如: ```csharp int[] numbers; numbers = new int[10]; // 创建一个包含10个元素的数组 numbers = new int[20]; // ...
### vc结构体数组长度计算 在C++编程中,经常需要定义包含自定义类型的数组,尤其是在涉及结构体(`struct`)的情况下。然而,在实际应用过程中可能会遇到结构体成员所占字节数不一致的问题,这主要是由于编译器...
在这个定义中,`name` 是一个字符数组,长度为 15。现在,我们想给这个结构体赋值,例如,学号为 7,姓名为 "Zhangsan"。 要给结构体赋值,我们需要使用 `memset` 函数来初始化结构体,然后使用赋值语句来设置成员...
最近的项目在做socket通信报文解析的时候,用到了结构体与字节数组的转换;由于客户端采用C++开发,服务端采用C#开发,所以双方必须保证各自定义结构体成员类型和长度一致才能保证报文解析的正确性,这一点非常重要...
这里的`BytesToStruct`方法接受一个字节数组和结构体的`Type`对象,首先检查字节数组的长度是否足够,然后分配内存,将字节数组的内容拷贝到内存,接着使用`Marshal.PtrToStructure`将内存中的数据转换为指定类型的...
在定义时,数组长度必须是常量表达式,不能包含运行时才能确定的变量值。 数组的声明和初始化是两个不同的步骤。数组可以在定义时进行初始化,即在声明时提供初始值,也可以在之后单独赋值。初始化时可以只给一部分...
首先,我们定义一个结构体`StructDemo`,它包含一个单字节变量`a`、一个单字节变量`c`、一个长度为3的字节数组`b`、一个单字节变量`d`和一个整数`e`。结构体的布局使用`StructLayoutAttribute`进行控制,设置`...
接着,我们使用结构体数组来存储多个职工的信息,并通过键盘输入来填充这些信息。最终,我们的目标是找出并打印出最高工资的职工。 首先,我们需要定义结构体类型。假设每个职工有以下属性: 1. `name`:职工的名字...
`MarshalAs(UnmanagedType.ByValArray, SizeConst = 32)`确保`UniqueCode`数组长度固定,符合C++的预期。 尽管做了这些调整,但仍然可能遇到问题,因为C++函数可能期望接收结构体指针或结构体数组指针。因此,我们...
如果结构体中的数组长度不是固定的,需要在转换过程中额外处理。 在实际应用中,我们常常会遇到包含数组的结构体,比如图像数据或网络协议数据。这时,我们可以先单独处理数组部分,将其转换为字节数组,然后合并到...
### 使用结构体数组实现通讯录管理的关键知识点 #### 一、结构体定义与用途 - **定义**: 在C语言中,`struct` 是一种用户自定义的数据类型,它允许我们组合不同类型的变量来构成一个整体。 - **示例**: ```c ...
}数组名[数组长度]; ``` 例如,如果我们想要创建一个表示学生信息的结构体,可以这样定义: ```c struct Student { int num; char name[20]; char id[20]; char birthday[10]; char sex; int age; int ...
基于C#调用C++ Dll结构体数组指针的问题详解 C#调用C++ Dll文件是一件很麻烦的事情,首先面临的是数据类型转换的问题。相信经常做C#开发的都和我一样把学校的那点C++基础都忘光了吧(语言特性类)。网上有一大堆得...
// 用结构体表示可变长度数组 List* list_init(size_t initial_size); // 初始化数组,指定初始容量 void list_free(List* lst); // 释放数组及其内存 int list_append(List* lst, int value); // 在数组末尾添加...
(1)利用结构体或数组模拟网络数据包结构。 (2)编码实现CRC算法,并将得到的校验位附加到网络数据包相应的位置。 (3)根据数据包的长度,随机生成一个数据包产生突变的位置,并对该位置的bit位模拟突变的产生。 ...
写在前面: 本文章旨在总结备份、方便以后查询,由于是个人总结,如有不对,欢迎指正...那么我们这时候如果我们用这个数组来接收串口接收信息,信息的格式是: 数据头 ->数据长度 ->数据区 ->数据校验 ->数据尾 假设数据