C语言变长数组使用详解

看如下代码:

#include<stdio.h>
typedef struct {
  int len;
  int array[];
}SoftArray;

int main() {
  int len = 10;
  printf("The struct's size is %d\n",sizeof(SoftArray));
  return 0;
}

运行结果:

[root@VM-0-7-centos mydoc]# ./a.out
The struct's size is 4

我们可以看出,_SoftArray结构体的大小是4,显然,在32位操作系统下一个int型变量大小刚好为4,也就说结构体中的数组没有占用内存。为什么会没有占用内

存,我们平时用数组时不时都要明确指明数组大小的吗?但这里却可以编译通过呢?这就是我们常说的动态数组,也就是变长数组。

先不要乱,让我们再看一段代码

#include<stdio.h>
#include<malloc.h>

typedef struct {
  int len;
  int array[];
}SoftArray;

int main() {
  int len = 10;
  SoftArray *p=(SoftArray*)malloc(sizeof(SoftArray) + sizeof(int)*len);
  printf("SoftArray size is %d\n", sizeof(SoftArray));
  free(p);

  return 0;
}

运行结果:

[root@VM-0-7-centos mydoc]# ./a.out
SoftArray size is 4

是不是有点奇怪,为什么申请了内存后结构体大小还是4呢?原因是动态申请的内存只是申请给数组拓展所用,从上个程序我们可以看出结构体的大小在创建时已经

确定了,array明确来说不算是结构体成员,只是挂羊头卖狗肉而已。

下面我们来看看关于变长数组的资料:

1、什么是变长数组?

变长数组既数组大小待定的数组, C语言中结构体的最后一个元素可以是大小未知的数组,也就是所谓的0长度,所以我们可以用结构体来创建变长数组。

2、变长数组有什么用途 ?

它的主要用途是为了满足需要变长度的结构体,为了解决使用数组时内存的冗余和数组的越界问题。

3、用法 :在一个结构体的最后 ,申明一个长度为空的数组,就可以使得这个结构体是可变长的。对于编译器来说,此时长度为0的数组并不占用空间,因为数组名

本身不占空间,它只是一个偏移量, 数组名这个符号本身代 表了一个不可修改的地址常量 (注意:数组名永远都不会是指针! ),但对于这个数组的大小,我们

可以进行动态分配,对于编译器而言,数组名仅仅是一个符号,它不会占用任何空间,它在结构体中,只是代表了一个偏移量,代表一个不可修改的地址常量!

对于变长数组的这个特点,很容易构造出变成结构体,如缓冲区,数据包等等

typedef struct {
  int len;
  int array[];
}SoftArray;

这样的变长数组常用于网络通信中构造不定长数据包,不会浪费空间浪费网络流量,比如我要发送1024字节的数据,如果用定长包,假设定长包的长度为2048,就

会浪费1024个字节的空间,也会造成不必要的流量浪费。

举个简单例子。

#include<stdio.h>
#include<malloc.h>

typedef struct {
  int len;
  int array[];
}SoftArray;

int main() {
  int len=10, i=0;
  SoftArray *p=(SoftArray*)malloc(sizeof(SoftArray)+sizeof(int)*len);
  p->len=len;
  for(i = 0;i < p->len;i++) {
    p->array[i] = i+1;
  }
  for(i = 0;i < p->len;i++) {
    printf("%d\n", p->array[i]);
  }
  free(p);

  return 0;
}

运行结果:

[root@VM-0-7-centos mydoc]# ./a.out

注意,内存对齐字节偏移
解决:资料【3】

#pragma pack(1)
struct node {
  int xxx;//4字节
  char yyy;//1字节
  char data[0];//零字节数组
}
#pragma pack()

参考资料:

1、https://www.cnblogs.com/Anker/p/3744127.html
2、https://www.cnblogs.com/veis/p/7073076.html
3、https://blog.csdn.net/dalerkd/article/details/69666716

到此这篇关于C语言变长数组使用详解的文章就介绍到这了,更多相关C语言变长数组内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • C语言变长数组 struct中char data[0]的用法详解

    今天在看一段代码时出现了用结构体实现变长数组的写法,一开始因为忘记了这种技术,所以老觉得作者的源码有误,最后经过我深思之后,终于想起以前看过的用struct实现变长数组的技术.下面是我在网上找到的一篇讲解很清楚的文章. 在实际的编程中,我们经常需要使用变长数组,但是C语言并不支持变长的数组.此时,我们可以使用结构体的方法实现C语言变长数组. struct MyData { int nLen; char data[0];}; 在结构中,data是一个数组名:但该数组没有元素:该数组的真实地址紧随结

  • C语言变长数组使用详解

    看如下代码: #include<stdio.h> typedef struct { int len; int array[]; }SoftArray; int main() { int len = 10; printf("The struct's size is %d\n",sizeof(SoftArray)); return 0; } 运行结果: [root@VM-0-7-centos mydoc]# ./a.out The struct's size is 4 我们可以

  • C语言 指针与数组的详解及区别

    C语言 指针与数组的详解及对比 通俗理解数组指针和指针数组 数组指针: eg:int( *arr)[10]; 数组指针通俗理解就是这个数组作为指针,指向某一个变量. 指针数组: eg:int*arr[10]; 指针数组简言之就是存放指针的数组: --数组并非指针&&指针并非数组 (1)定义一个外部变量: eg:int value=10; int *p=&value; 举例:当需要在一个函数中用这个变量时:externa int*p;而非extern int p[]; 分析:当用:e

  • C++11新特性之变长参数模板详解

    目录 C++11 变长参数模板 变长函数参数包 如何解参数包 sizeof()获得函数参数个数 递归模板函数 变参模板展开 结论 C++11 变长参数模板 在C++11之前,无论是类模板 还是函数模板,都只能按其指定的样子,接受一组固定数量的模板参数: 这已经大大提升了代码的复用! 在C++11之后,加入了新的表示方 法,允许任意个数.任意类别的模板参数,同时也不需要在定义时将参数的个数固定.更加像"黑魔法"了. template<typename... Ts> class

  • C语言动态内存管理malloc柔性数组示例详解

    目录 1.1为什么存在动态内存管理 1.2动态内存管理函数 1.2.1malloc 1.2.2free 1.2.3calloc 1.2.4realloc 1.3动态内存管理函数易错点 1.3.1对NULL指针的解引用操作 1.3.2对动态开辟空间的越界访问 1.3.3对非动态开辟内存使用free释放 1.3.4使用free释放一块动态开辟内存的一部分 1.3.5对同一块动态内存多次释放 1.3.6动态开辟内存忘记释放(内存泄漏) 2.1常见相关笔试题 2.2C/C++语言中的内存开辟 2.3柔性

  • C语言中指针和数组试题详解分析

    目录 数组题: 程序一(一维数组): 字符数组 程序二(字符数组): 程序三(字符数组): 程序四(字符数组): 程序五(字符数组): 二维数组 程序六( 二维数组): 指针题 程序七( 指针): 程序八( 指针): 程序九( 指针): 程序十( 指针): 程序十( 图): 程序十一( 指针): 程序十二( 指针): 程序十三( 指针): 指针 和 数组 试题解析 小编,在这里想说一下,c语言的最后一节 C预处理,可能还需要一些时间,因为小编,昨天才下载了虚拟机 和 linux 系统,还没开始安

  • C语言指针数组案例详解

    指针与数组是 C 语言中很重要的两个概念,它们之间有着密切的关系,利用这种 关系,可以增强处理数组的灵活性,加快运行速度,本文着重讨论指针与数组之 间的联系及在编程中的应用. 1.指针与数组的关系 当一个指针变量被初始化成数组名时,就说该指针变量指向了数组.如: char str[20], *ptr; ptr=str; ptr 被置为数组 str 的第一个元素的地址,因为数组名就是该数组的首地址, 也是数组第一个元素的地址.此时可以认为指针 ptr 就是数组 str(反之不成立), 这样原来对数

  • C语言 动态分配数组案例详解

    目录 一维动态数组的创建: 二维数组的创建: 很多人在编写C语言代码的时候很少使用动态数组,不管什么情况下通通使用静态数组的方法来解决,在当初学习C语言的时候我就是一个典型的例子,但是现在发现这是一个相当不好的习惯,甚至可能导致编写的程序出现一些致命的错误.尤其对于搞嵌入式的人来所,嵌入式系统的内存是宝贵的,内存是否高效率的使用往往意味着嵌入式设备是否高质量和高性能,所以高效的使用内存对我们来说是很重要的.那么我们在自己编写C语言代码的时候就应该学会使用动态数组,这也就是我这篇博客要给大家讲的,

  • C语言 指针数组进阶详解

    目录 指针与数组中的sizeof与strlen sizeof strlen 数组名 1.一维数组 整型数组 字符数组 指针数组 2.二维数组 指针笔试题 笔试题1 笔试题2 笔试题3 笔试题4 笔试题5 前言:指针与数组的知识往往让我们无法给自己定位,似乎是懂了,但真的碰上了又一言难尽.接下来有一些关于指针与数组的知识和例题讲解,来看看你对指针和数组到底有多了解吧! 指针与数组中的sizeof与strlen sizeof sizeof值关注占用空间的大小,单位是字节,不关注元素的类型,是一个操作

  • java数组基础详解

    数组 数组(Array):相同类型数据的集合. Java 数组初始化的两种方法: 静态初始化: 程序员在初始化数组时为数组每个元素赋值: 动态初始化: 数组初始化时,程序员只指定数组的长度,由系统为每个元素赋初值. 数组是否必须初始化 对于这个问题,关键在于要弄清楚数组变量和数组对象的差别.数组变量是存放在栈内存中的,数组对象是存放在堆内存中的.数组变量只是一个引用变量,他能够指向实际的数组对象. 所谓的数组初始化并非对数组变量初始化,而是对数组对象进行初始化. 定义数组 方式1(推荐,更能表明

随机推荐