C语言变长数组使用详解

 更新时间:2021年02月04日 11:35:09   作者:猴子居士  
这篇文章主要介绍了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语言变长数组内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • C++ 基本算法 冒泡法、交换法、选择法、实现代码集合

    C++ 基本算法 冒泡法、交换法、选择法、实现代码集合

    大家在学习C语言的时候,老师可能都会讲的几个算法,这里简单整理下,方便需要的朋友
    2013-04-04
  • C++数据精度问题(对浮点数保存指定位小数)

    C++数据精度问题(对浮点数保存指定位小数)

    这篇文章主要介绍了对浮点数保存指定位小数。比如, 1.123456. 要保存1位小数,,调用方法后, 保存的结果为: 1.1。 再比如,1.98765, 保存2位小数的结果为: 2.00,需要的朋友可以参考下
    2017-08-08
  • ubuntu系统vscodeC++编译环境配置与使用方式

    ubuntu系统vscodeC++编译环境配置与使用方式

    这篇文章主要介绍了ubuntu系统vscodeC++编译环境配置与使用方式,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-12-12
  • Opencv实现联合双边滤波

    Opencv实现联合双边滤波

    这篇文章主要为大家详细介绍了Opencv实现联合双边滤波,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2021-10-10
  • C语言题解Leetcode56合并区间实例

    C语言题解Leetcode56合并区间实例

    这篇文章主要为大家介绍了C语言题解Leetcode56合并区间实例详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2023-01-01
  • 基于Windows API实现遍历所有文件并删除的方法

    基于Windows API实现遍历所有文件并删除的方法

    这篇文章主要介绍了基于Windows API实现遍历所有文件并删除的方法,是win32应用程序的一个比较典型的文件操作应用技巧,需要的朋友可以参考下
    2015-04-04
  • C语言预编译#define(预处理)

    C语言预编译#define(预处理)

    这篇文章主要介绍了C语言预编译#define(预处理),#define 机制包括了一个机制,允许把参数替换到文本中,这种实现通常称为宏或者宏定义,下文更多的相关资料介绍需要的小伙伴可以参考一下
    2022-04-04
  • C++类的构造与析构特点及作用详解

    C++类的构造与析构特点及作用详解

    本文章将会可能会涉及到汇编的知识,不过没有关系,我会讲的尽量通俗易懂;另外本篇文章开始前,建议了解下什么是函数重载,这个概念很简单的--有相同的函数名,但参数列表不相同的函数,就是函数重载
    2022-10-10
  • visual studio 2022一个不易发现的问题

    visual studio 2022一个不易发现的问题

    本文主要介绍了visual studio 2022一个不易发现的问题,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2022-07-07
  • Qt生成随机数的方法

    Qt生成随机数的方法

    本文主要介绍了Qt生成随机数,生成随机数主要用到了函数qsrand和qrand,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2021-11-11

最新评论