0长度char数组的使用

2023-10-29

需要引起注意的:ISO/IEC 9899-1999里面,这么写是非法的,这个仅仅是GNU C的扩展,gcc可以允许这一语法现象的存在。 
结构体最后使用0或1的长度数组的原因,主要是为了方便的管理内存缓冲区,如果你直接使用指针而不使用数组,那么,你在分配内存缓冲区时,就必须分配结构体一次,然后再分配结构体内的指针一次,(而此时分配的内存已经与结构体的内存不连续了,所以要分别管理即申请和释放)而如果使用数组,那么只需要一次就可以全部分配出来,(见下面的例子),反过来,释放时也是一样,使用数组,一次释放,使用指针,得先释放结构体内的指针,再释放结构体。还不能颠倒次序。
其实就是分配一段连续的的内存,减少内存的碎片化。
看示例程序:
例1:test_size.c
  struct tag1
  {
      int a;
      int b;
  }__attribute ((packed));
 
  struct tag2
  {
      int a;
      int b;
      char *c;
  }__attribute ((packed));


  struct tag3
  {
      int a;
      int b;
      char c[0];
  }__attribute ((packed));


  struct tag4
  {
      int a;
      int b;
      char c[1];
  }__attribute ((packed));


  int main()
  {
      struct tag2 l_tag2;
      struct tag3 l_tag3;
      struct tag4 l_tag4;


      memset(&l_tag2,0,sizeof(struct tag2));
      memset(&l_tag3,0,sizeof(struct tag3));
      memset(&l_tag4,0,sizeof(struct tag4));


      printf("size of tag1 = %d/n",sizeof(struct tag1));
      printf("size of tag2 = %d/n",sizeof(struct tag2));
      printf("size of tag3 = %d/n",sizeof(struct tag3));


      printf("l_tag2 = %p,&l_tag2.c = %p,l_tag2.c = %p/n",&l_tag2,&l_tag2.c,l_tag2.c);
      printf("l_tag3 = %p,l_tag3.c = %p/n",&l_tag3,l_tag3.c);
      printf("l_tag4 = %p,l_tag4.c = %p/n",&l_tag4,l_tag4.c);
      exit(0);
  }


__attribute ((packed)) 是为了强制不进行4字节对齐,这样比较容易说明问题。
程序的运行结果如下:
size of tag1 = 8
size of tag2 = 12
size of tag3 = 8
size of tag4 = 9
l_tag2 = 0xbffffad0,&l_tag2.c = 0xbffffad8,l_tag2.c = (nil)
l_tag3 = 0xbffffac8,l_tag3.c = 0xbffffad0
l_tag4 = 0xbffffabc,l_tag4.c = 0xbffffac4

从上面程序和运行结果可以看出:tag1本身包括两个32位整数,所以占了8个字节的空间。tag2包括了两个32位的整数,外加一个char *的指针,所以占了12个字节。tag3才是真正看出char c[0]和char *c的区别,char c[0]中的c并不是指针,是一个偏移量,这个偏移量指向的是a、b后面紧接着的空间,所以它其实并不占用任何空间。tag4更加补充说明了这一点。
其实本质上涉及到的是一个C语言里面的数组和指针的区别问题,char a[1]里面的a和char *b的b相同吗?char a[1]里面的a实际是一个常量,等于&a[0]。而char *b是有一个实实在在的指针变量b存在。所以,a=b是不允许的,而b=a是允许的。两种变量都支持下标式的访问.
其实,这种语法是GCC对C语言做的扩展,官方权威说明在这里:http://gcc.gnu.org/onlinedocs/gcc-4.1.2/gcc/Zero-Length.html#Zero-Length
Zero-length arrays are allowed in GNU C. They are very useful as the last element of a structure which is really a header for a variable-length object:
struct line {
int length;
char contents[0];
};            
struct line *thisline = (struct line *)malloc (sizeof (struct line) + this_length);
thisline->length = this_length;

In ISO C90, you would have to give contents a length of 1, which means either you waste space or complicate the argument to malloc
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

0长度char数组的使用 的相关文章

  • Node.js笔记-day04

    18 Node js 回调函数 Node js 异步编程的直接体现就是回调 异步编程依托于回调来实现 但不能说使用了回调后程序就异步化了 回调函数在完成任务后就会被调用 Node 使用了大量的回调函数 Node 所有 API 都支持回调函数
  • Linux关于文件或者目录的常见命令

    1 查看当前所在目录 print working directory 该命令的基本格式为 root localhost pwd 2 查看指定目录下所有的子目录或者文件列表 list 该命令的基本格式为 root localhost ls 选
  • Axios(万字详细教程)

    Axios介绍 1 Axios是什么 Axios是一个基于promise的HTTP库 类似于jQuery的ajax 用于http请求 可以应用于浏览器端和node js 既可以用于客户端 也可以用于node js编写的服务端 2 Axios
  • idea项目无法打包

    打包过程 点击maven 点击lifecycle后点击package 运行后出现 打包出错 原因是plugins标签里面缺少maven resources plugin依赖 需要在pom xml里面添加依赖
  • Zimg—轻量级图片服务器搭建利器

    在一个互联网应用中 图片扮演着越来越重要的角色 有稳定的可扩展的图片存储服务器就显得尤为的重要 云厂商们提供了便利的图片存储服务 花钱就可以解决了 这里简单介绍一个开源的一个分布式图片存储服务器 zimg 来自己搭建一个图片服务器 当然你也
  • 2022阿里巴巴全球数学竞赛 第4题 虎虎生威(盲盒问题、集卡问题)解决思路

    目录 题目 基础概念 数学期望 题解 虎生威 问题 水浒传108卡 问题 虎虎生威 问题 题目 来自 2022阿里巴巴全球数学竞赛 第4题 单选题 基础概念 数学期望 在概率论和统计学中 数学期望 mathematic expectatio
  • 机器学习好伙伴之scikit-learn的使用——特征提取

    机器学习好伙伴之scikit learn的使用 特征提取 什么是特征提取 sklearn中特征提取的实现 PCA 主成分分析 LDA 线性评价分析 应用示例 PCA部分 LDA部分 有些时候特征太多了 可以利用sklearn中自带的函数进行
  • Yii Framework 开发教程(48) 多国语言示例

    本例通过Yii Framework 开发教程 11 UI 组件 ActiveForm示例添加中文支持简要说明一下多国语言支持 详细文档可可以参考Yii文档 信息翻译是通过调用 Yii t 实现的 此方法会将信息从 源语言 翻译为 目标语言
  • DVWA学习之XSS(跨站脚本攻击)(超级详细)

    DVWA学习之XSS XSS 跨站脚本攻击 0x01 XSS Cross Site Script 简介 0x02 何为XSS 0x03 XSS存在的原因 0x04 XSS漏洞的危害 0x05 XSS 的分类及特点 1 存储型XSS 2 反射
  • 初识C语言(3)

    目录 8 函数 函数的特点就是简化代码 代码复用 9 数组 要存储 1 10 的数字 怎么存储 C 语言中给了数组的定义 一组相同类型元素的集合 9 1数组的定义 9 2数组的下标 C 语言规定 数组的每个元素都有一个下标 下标是从 0 开
  • 人工智能——机器学习,数据特征预处理,数据降维

    数据特征预处理 数据降维 处理方法 1 数值型数据 标准缩放 1 归一化 2 标准化 3 缺失值 2 类别型数据 one hot 编码 3 时间类型 时间的切分 下面是归一
  • Git --- 基础介绍

    Git 基础介绍 git 是什么 git 工作区 暂存区 资源库 git 文件状态 git branch 和 HEAD git 一次正常的git提交流程 git 是什么 Git是一款分布式源代码管理工具 版本控制工具 Git和其他传统版本控
  • HTTP 与 HTTPS 的区别

    HTTP 与 HTTPS 的区别 文章目录 HTTP 与 HTTPS 的区别 前言 一 基本概念 二 HTTP 与 HTTPS 区别 三 TCP 三次握手 四 HTTPS 的工作原理 我的公众号 前言 一 基本概念 HTTP HyperTe
  • 基于SSM+Vue游戏商城系统Java游戏攻略网站(源码调试+讲解+文档)

    作者 计算机源码社 个人简介 本人七年开发经验 擅长Java 微信小程序 Python Android等 大家有这一块的问题可以一起交流 学习资料 程序开发 技术解答 代码讲解 文档报告 JavaWeb项目 微信小程序项目 Python项目
  • Servlet(GenericServlet相关)

    Servlet是用于实现web浏览器和java程序的对应关系 通过浏览器请求服务器调用对应的java程序 就是Servlet的主要功能 一个使用Servlet的类必须实现Servlet接口 implements Servlet 并且实现其中
  • 服务器巡检规范

    服务器巡检规范 01 服务器主机巡检规范 02 服务器日常巡检细则 03 管理员账号管理规范 04 用户服务器系统使用规范 05 机房来访人员管理规范 06 主机防火墙管理规范 07 组织容器命名规范 08 服务器主机名命名规范 01 服务
  • js是如何单线程执行的

    据大家所知 js都是单线程执行的 那么就会接触到线程与进程 同步执行与异步执行 以及js单线程执行原理概念 一 进程与线程的概念 1 1 进程 进程是CPU进行资源分配的基本单位 浏览器使用的是多进程 一个标签对应一个进程 此进程负责管理各
  • 【视音频编程学习】开源音频加速方案Sonic、SoundTouch对比及实时处理音频的实验分析

    语音变速不变调是指保持音调和语义保持不变 语速变快或变慢 该过程表现为语谱图在时间轴上如手风琴般压缩或者扩展 那也就是说 基频值几乎不变 对应于音调不变 整个时间过程被压缩或者扩展 声门周期的数目减小或者增加 即声道运动速率发生改变 语速也
  • 分布式架构之服务注册中心选型

    互联网架构下 大部分系统已经转型分布式 其中服务注册发现中心 分布式服务中非常重要的组成部分 按需选择合适的注册中心 也变的尤为重要 一 Eureka Eureka是SpringCloud全家桶中非常重要的一个组件 主要是实现服务的注册和发

随机推荐