C语言变长数组data[0]
“xiaoqiuhan2009”通过精心收集,向本站投稿了4篇C语言变长数组data[0],以下是小编整理后的C语言变长数组data[0],仅供参考,希望能够帮助到大家。
篇1:C语言变长数组data[0]
1、前言
今天在看代码中遇到一个结构中包含char data[0],第一次见到时感觉很奇怪,数组的长度怎么可以为零呢?于是上网搜索一下这样的用法的目的,发现在linux内核中,结构体中经常用到data[0].这样设计的目的是让数组长度是可变的,根据需要进行分配,方便操作,节省空间。
2、data[0]结构
经常遇到的结构形状如下:
struct buffer
{
int data_len; //长度
char data[0]; //起始地址
};
在这个结构中,data是一个数组名;但该数组没有元素;该数组的真实地址紧随结构体buffer之后,而这个地址就是结构体后面数据的地址(如果给这个结构体分配的内容大于这个结构体实际大小,后面多余的部分就是这个data的内容);这种声明方法可以巧妙的实现C语言里的数组扩展。
写个程序对比char data[0],char *data, char data[],如下所示:
1 #include
2 #include
3 #include
4 #include
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 int main
25 {
26 printf(“sizeof(buff_st_1)=%u\n”, sizeof(buff_st_1));
27 printf(“sizeof(buff_st_2)=%u\n”, sizeof(buff_st_2));
28 printf(“sizeof(buff_st_3)=%u\n”, sizeof(buff_st_3));
29
30 buff_st_1 buff1;
31 buff_st_2 buff2;
32 buff_st_3 buff3;
33
34 printf(“buff1 address:%p,buff1.data_len address:%p,buff1.data address:%p\n”,
35 &buff1, &(buff1.data_len), buff1.data);
36
37 printf(“buff2 address:%p,buff2.data_len address:%p,buff2.data address:%p\n”,
38 &buff2, &(buff2.data_len), buff2.data);
39
40 printf(“buff3 address:%p,buff3.data_len address:%p,buff3.data address:%p\n”,
41 &buff3, &(buff3.data_len), buff3.data);
42
43 return 0;
44 }
从结果可以看出data[0]和data[]不占用空间,且地址紧跟在结构后面,而char *data作为指针,占用4个字节,地址不在结构之后。3、实际当中的用法
在实际程序中,数据的长度很多是未知的,这样通过变长的数组可以方便的节省空间。对指针操作,方便数据类型的转换。测试程序如下:
1 #include
2 #include
3 #include
4 #include
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);
篇2:C语言变长消息定义:柔性数组
在游戏前后端交换的过程中,经常会用到变成的消息体,因为有的内容的大小是位置的,例如一条微博,微博的内容大小是未知的,
一般的做法是定义一个char*类型的指针,然后指定其长度,代码如下:
typedef struct{ unsigned len; char* pData;}Msg;
使用的时候是这样的:
char str[] = “hello world!”; unsigned len = sizeof(str); Msg* m = (Msg*)malloc(sizeof(Msg)+len*sizeof(char)); m->len = len; m->pData = (char*)(m+1); memcpy(m+1, str, len); printf(“%d, %s\n”, m->len, m->pData);
有没有觉得时机上char* pData很多余呢?
因为数据时机的存储位置在m+1,我们可以直接得到这个指针,而不需要重新定义一个char* pData来报错这个位置。
这样带来了另一个问题就是,访问不方便,我们不能用结构体成员的方式来访问了,可以使用柔性数组,且看:
typedef struct{ unsigned len; char data[];}Message;
使用起来就是这样的:
Message* msg = (Message*)malloc(sizeof(Message) + len*sizeof(char)); msg->len = len; memcpy(msg->data, str, len); printf(“%d, %s\n”, msg->len, msg->data); free(msg);
来分完整代码对比下:
// array0.h
typedef struct{ unsigned len; char* pData;}Msg;typedef struct{ unsigned len; char data[];}Message;
// main.c
// test for 0 size array#include 试验目的 1、掌握一维数组和二维数组的定义、赋值和输入输出的方法; 2、掌握字符数组和字符串函数的使用; 3、掌握与数组有关的算法特别是排序算法。 二、实验内容 教材习题P1527.2 三、算法流程图 四、程序清单 include void main {inti,j,min,s,a[11]; printf“请输入数组 “; fori1;i10;i {printf“a[d]“,i; scanf“d“, } printf“ “; printf“原数据为 “; fori1;i10;i printf“5d“,a[i]; printf“ “; fori1;i9;i {mini; forji1;ja[j] minj; sa[i]; a[i]a[min]; a[min]s; }printf“排好序的数组为 “; fori1;i10;i printf“5d“,a[i]; printf“ “; } 五、运行结果 六、实验总结(调试分析和体会)这个星期我对使用数组进行程序设计的学习,在之前的基础上,我更加努力,课前先预习,上课认真听,经过我的努力我进步了很多,虽然有了很大的进步,但在学习上还是存在很多问题。但这次的作业比上周的条件结构程序好多了。经过自己的努力,我已经掌握一维数组和二维数组的定义、赋值和输入输出的方法;掌握字符数组和字符串函数的使用;掌握与数组有关的算法特别是排序算法。这一单元数组跟以前的选择结构程序设计和循环控制相比,内容要繁琐得多,程序语句没有以前那么明了,要经过认真的思考,在经过自己思考后,即使是自己懂得算法的原理后,要来调程序又困难重重,一个程序要经过认真思考和反复的调试程序,才能完成。在多次的练习下,我基本上能结合程序掌握一些算法。通过多次的实验操作,我的操作能力有了很大的进步,但在学习的过程中并非一帆风顺,特别是在对程序的语句上,问题特别多。但我经过耐心地操作和虚心地请教终于掌握了正确的操作方法 指针是c语言的精华,也是c语言的难点,它就像一把双刃剑,锋利无比但运用的不好也会给自己带来危害,后果比较严重,所以重点来说说指针。 很多初学者弄不清指针和数组到底有什么样的关系,为避免混淆不清,下面总结一下指针和数组的特性。 指针是保存数据的地址,任何存入指针变量的数据都会被当作地址来处理,指针变量本身的地址由编译器另外存储,存储在哪里,我们并不知道,间接访问数据,首先取得指针变量的内容,把它作为地址,然后从这个地址读或写入数据。 指针可以用间接访问操作符(_)访问,也可以用以下标的形式访问,指针一般用于动态数据结构。 数组是用来保存数据的,数组名代表的是数组首元素的地址而不是数组的首地址,所以数组p与&p是有区别的,虽然内容相同,但意义却不同,&p才是整个数组的首地址,数组名是整个数组的名字,数组内每个元素并没有名字,不能把数组当一个整体来进行读写操作。 当然数组在初始化时也有例外,如int p[]=“12345”是合法的。 数组可以以指针的形式访问如_(p+i);也可以以下标的形式访问p[i],但其本质都是p所代表的数组首元素的地址加上i_sizeof(类型)个字节作为数据的真正地址来进行访问的。 数组通常用于存储固定数目且数据类型相同的元素。 刚开始的时候我 有点分不清指针数组和数组指针,现在也总结一下,指针数组,首先它是一个数组,数组的每个元素都是指针,可以理解为“存储指针的数组”的简称,数组指针,首先它是一个指针,它指向一个数组,在32位系统下永远只占4个字节,至于它指向的数组有多少个字节,并不知道,可以理解为“指向数组的指针”。 举个例子,int _p1[10]与int (_p2) [10], 要理解这个问题,首先要清楚操作符的优先级,“[]” 的优先级比“_”的优先级高,所以首先p1与“[10]”结合构成一个数组p1[10],int _为修饰数组的内容,所以数组元素是指向int类型的指针,所以这个是指针数组,“()”的优先级比“[]”的优先级高,“_”与p2结合构成一个指针变量,int修饰数组的内容,即数组的每个元素,数组这里并没有名字,是个匿名数组,现在清楚了p2是一个指针,它指向一个包含10个int类型数据的数组,即为数组指针。 下面再说说内存管理,内存分为三个部分:静态区、堆、栈。 其实堆栈就是栈,而不是堆。 静态区是保存自动全局变量和static变量。 静态区的内容在整个程序的生命周期内都存在,由编译器在编译的时候分配。 堆是由malloc系统函数分配内存的。 其生命周期由free和delete决定。 栈保存局部变量。 栈上的内容只在函数范围内存在,当函数运行结束,这些内容也会自动被销毁。 再说说有关内存需要注意的地方,定义了指针变量,在使用之前一定要初始化使它指向一块合法的内存,不管什么时候,我们在使用指针之前一定要确保指针是有效的。 使用malloc系列函数分配内存,使用完之后应及时释放内存,以防止内存泄露。 最后总结的说一下学习c语言的方法就是编程编程再编程,理论学习与上机操作同时进行,另外在编程序的过程中要养成良好的编程习惯。 【C语言变长数组data[0]】相关文章: 3.c语言学习方法 4.c语言面试题 5.c语言实验报告 6.c语言练习题 7.C语言求职信 8.c语言学习心得 10.c语言课程设计计划书篇3:大一c语言数组实验心得
篇4:大一c语言数组实验心得






文档为doc格式