关于结构体中最后的 char [0]

2023-11-10

问题:结构体中最后定义一个类似 char p[0] 这样的成员,有何意义?

回复1:
这是个广泛使用的常见技巧,常用来构成缓冲区。比起指针,用空数组有这样的优势:
1.不需要初始化,数组名直接就是所在的偏移
2.不占任何空间,指针需要占用int长度空间,空数组不占任何空间。

从herryhuang(Herry)的回复看,你只是看到了表面,并没有想到这种特性是很有利用价值的。“这个数组不占用任何内存”,意味着这样的结构节省空间;“该数组的内存地址就和他后面的元素的地址相同”,意味着无需初始化,数组名就是后面元素的地址,直接就能当做指针使用。

这样的写法最适合制作动态buffer。因为可以这样分配空间:
malloc(sizeof(struct XXX)+ buff_len);
看出来好处没有?直接就把buffer的结构体和缓冲区一块分配了。用起来也非常方便,因为现在空数组其实变成了buff_len长度的数组了。
这样的好处是:
一次分配解决问题,省了不少麻烦。大家知道为了防止内存泄漏,如果是分两次分配(结构体和缓冲区),那么要是第二次malloc失败了,必须回滚释放第一个分配的结构体。这样带来了编码麻烦。其次,分配了第二个缓冲区以后,如果结构里面用的是指针,还要为这个指针赋值。同样,在free这个buffer的时候,用指针也要两次free。如果用空数组,所有问题一次解决。
其次,大家知道小内存的管理是非常困难的,如果用指针,这个buffer的struct部分就是小内存了,在系统内存在多了势必严重影响内存管理的性能。要是用空数组把struct和实际数据缓冲区一次分配大块问题,就没有这个问题。

如此看来,用空数组既简化编码,又解决了小内存碎片问题提高了性能,何乐不为?应该广泛采用。

如果你做过操作系统的开发或者嵌入式开发,这种技巧应该是见得滥了.

回复2:
关于这个问题,从楼主的代码来看,存在几个需要弄清楚的地方。第一,char p[0]是否合法;其次,如果非法,按照标准,合法的代码是怎样的?

先解释第一点,在ISO/IEC 9899-1999里面,这么写铁定是非法的,这个仅仅是GNU C的扩展,gcc可以允许这一语法现象的存在。考虑以下代码:
#include

int main(int argc, char* argv[]) 
{ 
  char ia[0]; 
  printf("%d\n", sizeof(ia)); 
  return 0; 
} 

这个在gcc里面编译,即使你使用了-Wall参数,gcc仍然会让这段代码通过……如果需要强制编译器按照ISO C标准进行编译,你需要给出-pedantic(或者-pedantic_error)参数,这样,编译器会报告:ISO C forbids zero-size array `ia’
这个仅仅是在C99没有出台的情况下,gcc为了使用类似于C99 flexible array member而做出的一个work-around,但是现在C99出现了,并且正式支持了flexible array member的语法,这样的一个GNU C扩展就有点显得不合时宜了……按照ISO/IEC 9899-1999的要求,flexible array member的定义应当是这样:

struct foo 
{ 
int variable; 
int bar[ ];//here!!!! this is the C99 flexible array member
}; 

这个才是符合标准要求的写法,当你的代码需要跨平台、跨编译器移植,并且需要这个特性的时候,这个才是唯一准确的写法!

本来这里有一个trick,只不过flexible array member将其标准化了而已。
原来的trick应该是写作

struct foo 
{ 
int variable; 
int i_am_a_trick[1]; 
}; 

作者:hbg-rohens
原文链接:https://www.cnblogs.com/rohens-hbg/articles/6772468.html

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

关于结构体中最后的 char [0] 的相关文章

  • 如何指定 set precision 舍入

    当流到 std 输出时 我可以指定 set precision 对双精度值进行舍入吗 ofile lt lt std setprecision 12 lt lt total run time TIME lt lt n Output 0 75
  • TFS API - 缓慢的 foreach 变更集迭代

    问题背景 我正在使用 TFS api 查询 TFS 服务器上的大范围 1 600 文件 我从每个文件中收集其所有 ChangesetId 然后将其收集在列表中 代码 这是我正在使用的代码 它可以正确生成 QueryHistory 方法中指定
  • C 语言中的套接字如何工作?

    我对 C 中的套接字编程有点困惑 You create a socket bind it to an interface and an IP address and get it to listen I found a couple of
  • C++11 中具有 C 链接的复杂类型

    我需要将 C 库的标头包含到我的 C 11 代码中 现在 标头提供了涉及大量的例程和数据结构double complex到处都是 例如 include
  • 如何在 C++ 中对四元结构进行有效排序?

    我有一个包含 x y z 和 w 成员的结构 如何高效排序 在 C 中首先按 x 然后按 y 按 z 最后按 w 如果你想实现字典排序 那么最简单的方法是使用std tie实现小于或大于比较运算符或函子 然后使用std sort http
  • 使用 strcpy 从整数生成指针,无需进行强制转换

    我不明白我做错了什么 我正在学习 C 很抱歉 如果这显然是错误的 但我正在尝试使用uthash http uthash sourceforge net 制作股票及其价格的哈希图 但是当我将股票添加到哈希映射时 我收到上述错误 我所做的就是从
  • Debug.WriteLine() 未命中

    我正在调试 Windows 服务 通过点击F5在 Visual Studio 2010 中 使用以下代码 In 程序 cs file static void Main if Environment UserInteractive We ar
  • .NET:EventHandler 竞争条件修复如何工作?

    以下模式用于在引发事件时避免竞争条件 以防另一个线程取消订阅 MyEvent 使其为空 class MyClass public event EventHandler MyEvent public void F EventHandler h
  • 如何正确实现带有 close 方法的处置模式(CA1063)

    框架设计指南 第二版 第 327 页 说 考虑提供方法Close 除了Dispose 如果接近 是该领域的标准术语 这样做时 重要的是使 Close 实现与Dispose并考虑实施IDisposable Dispose方法明确 因此 按照提
  • 等于方法实现助手 (C#)

    每次我编写一些数据类时 我通常都会花很多时间编写 IEquatable 实现 我写的最后一堂课是这样的 public class Polygon public Point Vertices get set 实施 IEquatable 是一项
  • C++在子类中调用虚方法

    我有以下课程 class A protected A inner public virtual void doSomething 0 class B public A void doSomething if inner NULL inner
  • 如何使用 HttpClient 验证 Pardot API

    我花了大约一天的时间尝试对 Pardot API 进行身份验证 它不喜欢我尝试发布消息正文的方式 所以我想发布对我有用的解决方案 如果您有任何建议或替代方案 我想听听 ServicePointManager SecurityProtocol
  • 如何在PropertyGrid中自定义绘制GridItem?

    我想以与所有者在 ListView 详细信息 和其他控件中绘制项目类似的方式在 PropertyGrid 中绘制属性值 如果将属性声明为 Color 类型 则其值将使用字符串描述旁边的颜色样本来绘制 如果属性是图像类型 则在字符串描述旁边绘
  • 随机排列

    我无法找到一种随机洗牌元素的好方法std vector经过一些操作后 恢复原来的顺序 我知道这应该是一个相当简单的算法 但我想我太累了 由于我被迫使用自定义随机数生成器类 我想我不能使用std random shuffle 无论如何这没有帮
  • 比较 C# 中的对象属性[关闭]

    Closed 这个问题是基于意见的 help closed questions 目前不接受答案 Locked 这个问题及其答案是locked help locked posts因为这个问题是题外话 但却具有历史意义 目前不接受新的答案或互动
  • 通过开源 PCL 使用 API 查看 3D 点云

    我使用 ToF 飞行时间 相机来获取 XYZ 格式的深度数据 为了实现 3D 点云的可视化目的 我想使用开源 PCL 提供的 API 网址为http pointclouds org documentation tutorials pcl v
  • Opencv 对象检测:ORB GPU 检测器和 SURF GPU 描述符提取器

    我只是做了一个小实验来尝试不同的检测器 描述符组合 我的代码使用 ORB GPU 检测器来检测特征 并使用 SURF GPU 描述符来计算描述符 我使用 BruteForceMatcher GPU 来匹配描述符 并使用 knnMatch 方
  • 在 C# 中设置风扇速度

    我知道以前有人问过这个问题 但我似乎无法让它发挥作用 我已调用以下内容 using System Management using System Management Instrumentation using System Runtime
  • QT C++ QRegularExpression 多个匹配

    我想使用正则表达式从 QString html 中提取信息 我明确想使用正则表达式 无解析器解决方案 和类Q正则表达式 http qt project org doc qt 5 0 qtcore qregularexpression htm
  • 如何在 C# 中将 json 转换为平面结构

    我正在尝试用 C 编写函数 将 JSON 转换为键 值对 它应该支持数组 例如下面的 JSON title title value components component id id1 menu title menu title1 tit

随机推荐

  • 数据结构--环形队列的介绍与实现

    数据结构 环形队列实现 一 环形队列实现原理 环形队列的几个判断条件 二 代码实现 1 环形队列类 CircleQueue 2 环形队列类测试类 3 程序运行结果 4 完整代码 环形队列可以用数组实现 也可以使用循环链表实现 在使用数组实现
  • 2023前端面试题总结(vue,react)

    Vue 1 MVC与MVVM的区别 MVC和MVVM的区别并不是VM完全取代了C ViewModel存在目的在于抽离Controller中展示的业务逻辑 而不是替代Controller 其它视图操作业务等还是应该放在Controller中实
  • Vue-条件渲染和循环渲染

    文章目录 条件渲染 循环渲染 条件渲染 条件渲染指令是用来辅助开发者控制DOM的显示与隐藏 条件渲染指令有如下两个 分别是 v show和v if v show和v if的区别 v show是通过动态的为元素添加或移除display non
  • 【计算机视觉】ViT:Vision Transformer 讲解

    有任何的书写错误 排版错误 概念错误等 希望大家包含指正 在阅读本篇之前建议先学习 自然语言处理 Attention 讲解 自然语言处理 Transformer 讲解 自然语言处理 BERT 讲解 ViT Vision Transforme
  • 眼光独到便能发现刷脸支付带来的商机

    2020年 属于扫码支付的时代已经过去 刷脸支付时代悄然而至 在5G和数字化时代的引领下 刷脸支付将充满无限可能 率先发现商机并加入刷脸支付的人 可以早日占据移动支付刷脸支付市场的一片天空 在现金支付还是主流的时代 人们对扫码支付的概念十分
  • 坦克大战JAVA程序(韩顺平老师)

    坦克大战java程序 目前程序完成的功能 1 打开游戏选择继续上一局游戏还是重新开始 2 页面打开后有一段背景音乐 增加体验感 3 页面显示击毁的敌方坦克数量 4 玩家坦克由wasd键控制方向 j键控制射击 敌方坦克被击中后 出现爆炸效果
  • Codeforces Round #752 (Div. 2) C. Di-visible Confusion (思维暴力))

    题解 根据题意如果2 i 1范围内没法整除就删掉嘛 所以这题其实最多暴力前100就行 证明 因为如果前100有不能整除的 那么这个数一定可以删掉 但是如果前100都能被整除 也就是前100每个数都是这个数的因子 那么这个数就太大了绝对超过了
  • 力扣简单算法题

    简单题 一分类 数组 1 两数之和 哈希表 给定一个整数数组 nums 和一个整数目标值 target 请你在该数组中找出 和为目标值 target 的那 两个 整数 并返回它们的数组下标 你可以假设每种输入只会对应一个答案 但是 数组中同
  • 数据结构作业:时间复杂度和二叉树

    计算时间复杂度 int x 0 i j 1 for i 1 i
  • 小程序可以通过以下几种方式下发消息

    1 模板消息 小程序可以通过模板消息向用户发送通知 例如订单状态更新 活动提醒等 开发者需要先在小程序后台设置好模板消息 并获取到模板消息的模板ID 然后在代码中调用相应的API 将模板消息的内容填充并发送给用户 以下是一个示例代码 用于发
  • CSS开发技巧(四):解决flex多行布局的行间距异常、子元素高度拉伸问题

    在使用flex布局时 若出现换行 有两种较为特殊的现象是值得我们研究的 子元素高度被拉伸 其实际高度大于它的内容高度 各行子元素之间的行间距过大 甚至我们根本没有给子元素设置margin 现在我们将要探究引发这两种现象的原因及解决方案 一
  • for循环三种跳出循环的方法(retrun、continue、break)Mark

    1 continue 指的是跳出当前循环 即不执行continue后的语句 直接进入下次循环 continue语句和break语句差不多 不同的是 它不是退出一个循环 而是跳出当前循环 进行下一轮循环 public static void
  • mac 下的 bash gradle command not found

    最近在用android studio 使用命令行打包的时候出现 bash gradle command not found这个问题 其实也就是因为自己唑gradle的环境变量给弄丢了 但是由于来自大山的孩子对于mac不是很熟 所以不知道咋去
  • Redis3.0.7 cluster/集群 安装配置教程

    原文地址 http blog csdn net ouchuquan article details 50884479 参考地址 http doc redisfans com topic cluster tutorial html http
  • ios 轻 App

    整体建议 使用在一些展示项目中 少量数据产生的 需要借助apple平台让用户了解到的 另外 该功能也可以作为品牌宣传 特别是一些景点之类 简单 页面的 轻 App 是 app 的一小部分 因此您可以使用 iOS SDK 在与完整 app 相
  • Rational rose 2007 下载和安装教程

    文章目录 Rational rose 简介 一 下载Rational rose 2007 二 安装Rational rose 2007 三 激活Rational Rose 2007 四 启动Rational Rose 2007 Ration
  • C++多态性

    本文参考浅谈C 多态性 多态性可以简单地概括为 一个接口 多种方法 程序在运行时才决定调用的函数 它是面向对象编程领域的核心概念 多态 polymorphism 字面意思多种形状 C 多态性是通过虚函数来实现的 虚函数允许子类重新定义成员函
  • 11.16---遍历数组赋值给对象失败,const定义常量不能重新再赋值,render的参数

    1 遍历数组赋值给对象失败 取到的都是最后一项的值 let result item list forEach function value item a value a item b value b result pust item 结果得
  • 字符串合并并处理(C++实现)

    按照指定规则对输入的字符串进行处理 详细描述 将输入的两个字符串合并 对合并后的字符串进行排序 要求为 下标为奇数的字符和下标为偶数的字符分别从小到大排序 这里的下标意思是字符在字符串中的位置 对排序后的字符串进行操作 如果字符为 0 9
  • 关于结构体中最后的 char [0]

    问题 结构体中最后定义一个类似 char p 0 这样的成员 有何意义 回复1 这是个广泛使用的常见技巧 常用来构成缓冲区 比起指针 用空数组有这样的优势 1 不需要初始化 数组名直接就是所在的偏移 2 不占任何空间 指针需要占用int长度