/* C语言零长度数组大小和取值问题 */
#include <stdio.h>
#include <stdlib.h>
#include <string.h> struct str
{
int type;
char s[];//零长度的数组
}; struct foo
{
int type;
char *s;
}; void test()
{
printf("str size is [%d] \n", sizeof(struct str)); //打印 4
/*
使用GDB查看汇编代码
对于struct str 结构体中的 char s[0]来说,汇编代码用了lea指令,lea 0x04(%rax), %rdx
对于struct foo 结构体中的 char*s来说,汇编代码用了mov指令,mov 0x04(%rax), %rdx
lea全称load effective address,是把地址放进去,而mov则是把地址里的内容放进去。
访问成员数组名其实得到的是数组的相对地址,而访问成员指针其实是相对地址里的内容(这和访问其它非指针或数组的变量是一样的)
对于数组 char s[10]来说,数组名 s 和 &s 都是一样的。char s[0] 表示的是地址。char*s 表示的地址的内容
*/ printf("foo size is [%d] \n", sizeof(struct foo)); //32位机器上 打印8 //零长度的数组的打印
struct str s1;
printf("Arrays of Length Zero print [%p] \n", s1.s);
printf("Arrays of Length Zero print [%p] \n", &s1.s); //结果相同 打印的是char s[0] 的地址 struct foo f1;
//printf("Arrays of Length Zero print [%x] \n", f1.s); //程序core down 验证 char*s 访问成员指针其实是相对地址里的内容 } //验证char s[]更多的类似于一个占位符
struct str1
{
int length;
int flags;
char s[];//零长度的数组(Flexible Array)
}; void test1()
{
//零长度数组的占位符功能
//注意 char s[]更多的类似于一个占位符,并非结构体成员,所以计算结构体大小时,并没有char s[]
printf("===size==='[%d]====\n", sizeof(struct str1));
} int main()
{ test1();
printf("-----ok------\n");
getchar();
return ;
}
/* C语言零长度数组使用 */
#include <stdio.h>
#include <stdlib.h>
#include <string.h> #define GTS_HDR(s) ((struct str *)((s)-(sizeof(struct str)))) struct str
{
int length;
unsigned char flags;
char s[];//零长度的数组(Flexible Array)
}; /*
零长度的数组优势
第一个优点是,方便内存释放。如果我们的代码是在一个给别人用的函数中,你在里面做了二次内存分配,并把整个结构体返回给用户。
用户调用free可以释放结构体,但是用户并不知道这个结构体内的成员也需要free,所以你不能指望用户来发现这个事。所以,
如果我们把结构体的内存以及其成员要的内存一次性分配好了,并返回给用户一个结构体指针,用户做一次free就可以把所有的内存也给释放掉。 第二个优点是,这样有利于访问速度。连续的内存有益于提高访问速度,也有益于减少内存碎片。 零长度数组的具体使用可以参考redis中sds结构
*/ char * create(void)
{
int len = ;
struct str *s1 = NULL; s1 = calloc(, sizeof(struct str) + len);
//模仿redis中sds结构
s1->flags = ;
s1->length = len; //注意 char s[0]只是一个占位符,不占用实际内存空间,所以成员变量char s[0]的offset不是s1->s,而是s1+sizeof(struct str)
//因此也不应该对外暴露struct str 结构,防止用户操作struct str 的内存空间
strcpy((char *)s1 + sizeof(struct str), "hello world "); //错误示例 打印空
printf("====error show==[%s]=====\n", s1->s); return (char *)s1 + sizeof(struct str);
} void test()
{
char * s = create(); printf("--s is -[%s]---\n", s); } int main()
{ test();
printf("-----ok------\n");
getchar();
return ;
}

 零长度数组只有GUN/GCC支持 别的厂家可能不支持,此时需要用 char data[1]来代替

C语言 结构体中的零长度数组的更多相关文章

  1. c语言结构体中的一个char数组怎么赋值?

    目录 前景提示 这里的结构体处理的步骤 一.char数组类型的处理 二.char数组指针类型的处理 三.全部代码 1. char数组 2. char数组指针 结语 前景提示 定义一个结构体,结构体中有 ...

  2. 在C语言结构体中添加成员函数

    我们在使用C语言的结构体时,经常都是只定义几个成员变量,而学过面向对象的人应该知道,我们定义类时,不只是定义了成员变量,还定义了成员方法,而类的结构和结构体非常的相似,所以,为什么不想想如何在C语言结 ...

  3. c语言结构体中的冒号的用法

    结构体中常见的冒号的用法是表示位域. 有些信息在存储时,并不需要占用一个完整的字节,   而只需占几个或一个二进制位.例如在存放一个开关量时,只有0和1   两种状态,   用一位二进位即可.为了节省 ...

  4. C语言 结构体中的成员域偏移量

    //C语言中结构体中的成员域偏移量 #define _CRT_SECURE_NO_WARNINGS #include<stdio.h> #include<stdlib.h> # ...

  5. C语言结构体中的函数指针

      这篇文章简单的叙述一下函数指针在结构体中的应用,为后面的一系列文章打下基础 本文地址:http://www.cnblogs.com/archimedes/p/function-pointer-in ...

  6. C语言 结构体中属性的偏移量计算

    //计算结构体偏移量 #include<stdio.h> #include<stdlib.h> #include<string.h> //详解:对于offscfof ...

  7. 嵌入式C语言自我修养 05:零长度数组

    5.1 什么是零长度数组 顾名思义,零长度数组就是长度为0的数组. ANSI C 标准规定:定义一个数组时,数组的长度必须是一个常数,即数组的长度在编译的时候是确定的.在ANSI C 中定义一个数组的 ...

  8. GNU C中的零长度数组

    http://blog.csdn.net/ssdsafsdsd/article/details/8234736 在标准C和C++中,长度为0的数组是被禁止使用的.不过在GNU C中,存在一个非常奇怪的 ...

  9. C语言结构体中字符数组的问题

    第一个程序 #include <stdio.h> #include <string.h> typedef struct student { char name[10]; int ...

随机推荐

  1. (网络数据交互)Android解析Internet的Json资源文件

    常用的Internet数据解析格式和工具: 网页显示的json数据如下: {"type":"FeatureCollection","metadata& ...

  2. Android的系统属性:build.propSystemProperties

    获取build.prop的键值信息: String sn = SystemProperties.get(SN_INFO); 其中key值为: public static final String SN ...

  3. 潭州课堂25班:Ph201805201 爬虫高级 第十课 Scrapy-redis分布 (课堂笔记)

    利用 redis 数据库,做 request 队列,去重,多台数据共享, scrapy 调度 基于文件每户,默认只能在单机运行, scrapy-redis 默认把数据放到 redis 中,实现数据共享 ...

  4. [CF1039D]You Are Given a Tree

    [CF1039D]You Are Given a Tree 题目大意: 给定一棵\(n(n\le10^5)\)个节点的树.对于每一个正整数\(k(1\le k\le n)\),求最多能找出多少条包含\ ...

  5. Android 蓝牙4.0 BLE (onServicesDiscovered 返回 status 是 129,133时)

    Android ble (Bluetooth Low Energy) 蓝牙4.0,也就是说android 4.3+, API level >= 18,且支持蓝牙4.0的手机才可以使用. BLE是 ...

  6. 全排列 ---java

    排列的一种好方法,用链表来记录数据,简单明了,简称模板,值得记录 public class main{ static int count=0; public static void f(List< ...

  7. openstack 之~horizon部署

    第一:部署horizon环境: 安装部署memcache 安装软件包 yum install memcached python-memcached 启动memcache并且设置开机自启动 system ...

  8. poj1852 Ants(思维)

    https://vjudge.net/problem/POJ-1852 最短时间显然是各自往靠近端点的地方走. 最长时间关键是要想到,折返和擦肩其实是一样的,可以当成两只蚂蚁换了个位子,最终求max是 ...

  9. Vue 2.3、2.4 知识点小结

    2.3 style 多重值: <div :style="{ display: ['-webkit-box', '-ms-flexbox', 'flex'] }">< ...

  10. Android必学之数据适配器BaseAdapter

    什么是数据适配器? 下图展示了数据源.适配器.ListView等数据展示控件之间的关系.我们知道,数据源是各种各样的,而ListView所展示数据的格式则是有一定的要求的.数据适配器正是建立了数据源与 ...