C语言 结构体中的零长度数组
/* 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语言 结构体中的零长度数组的更多相关文章
- c语言结构体中的一个char数组怎么赋值?
目录 前景提示 这里的结构体处理的步骤 一.char数组类型的处理 二.char数组指针类型的处理 三.全部代码 1. char数组 2. char数组指针 结语 前景提示 定义一个结构体,结构体中有 ...
- 在C语言结构体中添加成员函数
我们在使用C语言的结构体时,经常都是只定义几个成员变量,而学过面向对象的人应该知道,我们定义类时,不只是定义了成员变量,还定义了成员方法,而类的结构和结构体非常的相似,所以,为什么不想想如何在C语言结 ...
- c语言结构体中的冒号的用法
结构体中常见的冒号的用法是表示位域. 有些信息在存储时,并不需要占用一个完整的字节, 而只需占几个或一个二进制位.例如在存放一个开关量时,只有0和1 两种状态, 用一位二进位即可.为了节省 ...
- C语言 结构体中的成员域偏移量
//C语言中结构体中的成员域偏移量 #define _CRT_SECURE_NO_WARNINGS #include<stdio.h> #include<stdlib.h> # ...
- C语言结构体中的函数指针
这篇文章简单的叙述一下函数指针在结构体中的应用,为后面的一系列文章打下基础 本文地址:http://www.cnblogs.com/archimedes/p/function-pointer-in ...
- C语言 结构体中属性的偏移量计算
//计算结构体偏移量 #include<stdio.h> #include<stdlib.h> #include<string.h> //详解:对于offscfof ...
- 嵌入式C语言自我修养 05:零长度数组
5.1 什么是零长度数组 顾名思义,零长度数组就是长度为0的数组. ANSI C 标准规定:定义一个数组时,数组的长度必须是一个常数,即数组的长度在编译的时候是确定的.在ANSI C 中定义一个数组的 ...
- GNU C中的零长度数组
http://blog.csdn.net/ssdsafsdsd/article/details/8234736 在标准C和C++中,长度为0的数组是被禁止使用的.不过在GNU C中,存在一个非常奇怪的 ...
- C语言结构体中字符数组的问题
第一个程序 #include <stdio.h> #include <string.h> typedef struct student { char name[10]; int ...
随机推荐
- 1489 ACM 贪心
题目:http://acm.hdu.edu.cn/showproblem.php?pid=1489 题意:为负数表示买酒,正数表示买酒,每两家人之间为one unit of work.问最小的work ...
- 利用"SQL"语句自动生成序号的两种方式
1.首先,我们来介绍第一种方式: ◆查询的SQL语句如下: select row_number() over (order by name) as rowid, sysobjects.[id] fro ...
- instanceof详解
instanceof 用于确定一个 PHP 变量是否属于某一类 class 的实例: <?php class MyClass { } class NotMyClass { } $a = new ...
- ASP.NET Core Docker jexus nginx部署-CentOS实践版
本文用图文的方式记录了我自己搭建centos+asp.net core + docker + jexus + nginx的整个过程,希望对有同样需求的朋友有一定的参考作用. 本文主要内容如下: cen ...
- 前端工程化系列[06]-Yeoman脚手架核心机制
在前端工程化系列[05] Yeoman脚手架使用入门这边文章中,对Yeoman的使用做了简单的入门介绍,这篇文章我们将接着探讨Yeoman这个脚手架工具内部的核心机制,主要包括以下内容 ❏ Yeoma ...
- HTML动画 request animation frame
在网页中,实现动画无外乎两种方式.1. CSS3 方式,也就是利用浏览器对CSS3 的原生支持实现动画:2. 脚本方式,通过间隔一段时间用JavaScript 来修改页面元素样式来实现动画.接下来我们 ...
- cookie 跨域解决方法
1.Nginx 正向和反向代理的区别 正向代理和反向代理的区别:正向代理隐藏真实客户端,反向代理隐藏真实服务端,图示: 2.cookie跨域问题 因为cookie存在跨域问题,其中一个解决方法是,设置 ...
- EAS开发之挂菜单
一:以管理员账号登录 二:挂菜单 点击菜单栏"系统"——客户化菜单编辑——选中上级目录——点击 新建——命名.键入唯一编码,把ui.java类的全路径,拷贝到 ...
- 再看C# ThreadPool与Task的认识总结
工作线程与I/O线程 在ThreadPool中有这样一个方法: public static bool SetMaxThreads(int workerThreads, int completi ...
- ABC卡
如今在银行,P2P等各种贷款业务机构,普遍使用信用评分,对客户实行打分制,以期对客户有一个优质与否的评判.但是不是所有人都知道信用评分卡还分A,B,C卡三类!所以,如果你只知道ABC是Gary的ABC ...