欢迎来到个人简历网!永久域名:gerenjianli.cn (个人简历全拼+cn)
当前位置:首页 > 范文大全 > 实用文>C语言变长数组data[0]

C语言变长数组data[0]

2025-02-11 07:31:33 收藏本文 下载本文

“xiaoqiuhan2009”通过精心收集,向本站投稿了4篇C语言变长数组data[0],以下是小编整理后的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#include#include#include “array0.h”int main{ 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); free(m); // 柔性数组 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); system(“pause”); return 0;}

篇3:大一c语言数组实验心得

试验目的 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“

“; } 五、运行结果 六、实验总结(调试分析和体会)这个星期我对使用数组进行程序设计的学习,在之前的基础上,我更加努力,课前先预习,上课认真听,经过我的努力我进步了很多,虽然有了很大的进步,但在学习上还是存在很多问题。但这次的作业比上周的条件结构程序好多了。经过自己的努力,我已经掌握一维数组和二维数组的定义、赋值和输入输出的方法;掌握字符数组和字符串函数的使用;掌握与数组有关的算法特别是排序算法。这一单元数组跟以前的选择结构程序设计和循环控制相比,内容要繁琐得多,程序语句没有以前那么明了,要经过认真的思考,在经过自己思考后,即使是自己懂得算法的原理后,要来调程序又困难重重,一个程序要经过认真思考和反复的调试程序,才能完成。在多次的练习下,我基本上能结合程序掌握一些算法。通过多次的实验操作,我的操作能力有了很大的进步,但在学习的过程中并非一帆风顺,特别是在对程序的语句上,问题特别多。但我经过耐心地操作和虚心地请教终于掌握了正确的操作方法

篇4:大一c语言数组实验心得

指针是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]】相关文章:

1.深度理解C语言的指针与数组

2.c中指针指针、指针的指针、指针数组和数组指针

3.c语言学习方法

4.c语言面试题

5.c语言实验报告

6.c语言练习题

7.C语言求职信

8.c语言学习心得

9.C语言实验报告《指针》

10.c语言课程设计计划书

下载word文档
《C语言变长数组data[0].doc》
将本文的Word文档下载到电脑,方便收藏和打印
推荐度: 评级1星 评级2星 评级3星 评级4星 评级5星
点击下载文档

文档为doc格式

  • 返回顶部