结构体浅析
来源:互联网 发布:虚拟串口调试软件 编辑:程序博客网 时间:2024/06/03 20:58
结构体浅析
C语言提供了两种聚合数据类型:数组和结构。结构变量属于标量类型(例如:int,char等),所以可以像对待标量那样子对待结构变量,
1. 结构变量可以作为传递给函数的参数
2. 可以作为返回值
3. 相同类型的结构变量还可以互相赋值
结构体声明和定义变量的几种模式
1. 声明:struct tag{member_list};
定义:struct tag variable1;
2. 声明:struct tag{member_list}variable_list;
定义:已在variable_list定义,亦可使用 1 中定义方法
3. 声明:typedef struct tag{member_list};
定义:tag variable1;
4. (使用频率最高的方式,可以少写很多东西)
声明:typedef struct tag{member_list}variable_list;
定义:已在variable_list定义,亦可使用 3 中定义方法
5. (几乎不这样子使用,只有在声明时能够定义变量,很不方便)
声明+定义:struct {member_list}variable_list;
注:
member_list可以包括:普通标量(int 、char、标量指针、结构体指针),其他结构体 。
variable_list可以是普通变量,数组,指针等
结构的自引用
上面已经说过了member_list的成员了,那么现在我们再来讨论下成员是否可以有自身结构,首先看看下面的这两个声明结构
【错】
struct test {
int a;
struct test1 b;
};
【对】
struct test {
int a;
struct test1 *b;
};
显然区别就在‘*’,前者的成员是结构b,而后者的成员是结构指针b,前者的成员就是自己,成员里面还有成员,这样子就陷入了死循环,编译器绝对不允许这样的事情出现,而后者的结构指针就不一样了,因为指针所占的空间大小是一定的,所以编译器可以很轻易的就给该结构变量分配内存空间
注:struct{
Int a;
Variable b;
}*Variable;
它是错误的,因为在member_list中,变量Variable还没有声明,编译器还不知道Variable是个什么东西,所以是上面的声明是错误的,正确的应该是下面的:
struct test{
Int a;
struct test *b;
}*Variable;
结构体的互相引用
结构体的互相引用,必然存在这样的问题:无论先声明哪个结构体
,它里面总包含另一个结构体,但是我们又没有声明另一个结构体,反之亦然。因而我们可以利用不完整的声明解决这个问题
例如:我们需要结构体A中包含结构体B,结构体B中包含结构体A。
struct B;
struct A{
struct B;
};
struct B{
struct A;
};
这样子就完美解决结构体互相引用的问题了。
结构的存储
大家先看看下面这两个结构体:
typedef struct first{
int a;
char b;
char c;
};
typedef struct second{
char b;
int a;
char c;
};
他们两个有什么区别呢?
只是member_list的顺序不同罢了,但是由于边界对齐技术(CPU在工作时只能按照某长度的整倍数为边界进行内存操作)的存在,因而产生了不同的效率。
first:
█
█
█
█
█
b
█c
前面的四个为a占用的空间,紧接着的是b,c占用的,最后的两个由于对齐而保留,下次cpu将从空白后面的地址开始访问内存。空间利用率:75%
Second:
█
b
█
█
█
█
█
c
前面的四个空间存储的是b,中间的是a,下来的是c,空间利用率:50%
下面是测试我的测试程序,仅供大家参考:
注:函数offsetof(type,member) type:结构体类型; member:结构体成员; 功能:求得member开始存储的位置距离存储的位置偏移的字节数
运行结果截图如下:
<img src="http://img.blog.csdn.net/20140620233055156?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvY29sZW9wdGlsZQ==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center" alt="" />经过上面的许多测试,我们可以得出这样的结论:尽量把占用空间最大的类型放在member_list的最上面,这样子可以使空间利用率最大,甚至达到100%,节约的这点内存空间在程序创建成百上千个结构上体现的尤为明显。
作为函数参数的结构
例:typedef struct {
int stu_id;
char stu_name[20];
}stu;
void print( stu student)
{
Printf(“id:%d\n”,student.stu_id;);
Printf(“name:%s\n”,student.stu_name);
}
这样子传结构体参数是可以的,可是由于在c语言中传递传递参数就是把参数拷贝一份,然后供函数使用,这样子拷贝就有点多了,远不如传递结构体指针简单,但是传递指针可能改变结构内容,因而我们可以加上关键字const,实现如下:
void print( stu const *student)
{
Printf(“id:%d\n”,student->stu_id;);
Printf(“name:%s\n”,student->stu_name);
}
传递指针的效率就很高了,只需要拷贝一个指针标量就行了,是不是很能提高效率,尤其是在大量调用一个函数的情况下。
#include<stdio.h>#include<stddef.h>#include<windows.h> typedef struct test1{ char c; double a; char b; };typedef struct test2{ char b; char c; double a; };typedef struct test3{ double a; char b; char c; };typedef struct test4{ double a; int b; int c; }; int main(){ /*测试编译器给予不同类型标量的大小*/ printf("测试编译器给予不同类型标量的大小!\n"); printf("sizeof(char):%d\n",sizeof(char)); printf("sizeof(int):%d\n",sizeof(int)); printf("sizeof(double):%d\n\n",sizeof(double)); /*测试不同排序下结构体的空间利用率*/ printf("sizeof(struct test1):%d\n",sizeof(struct test1)); printf("offsetof(struct test1,c):%d\n",offsetof(struct test1,c)); printf("test1空间利用率:%.2lf\n\n",(double)(sizeof(double)+2*sizeof(char))/(double)sizeof(struct test1)); printf("sizeof(struct test2):%d\n",sizeof(struct test2)); printf("offsetof(struct test2,c):%d \n",offsetof(struct test2,c)); printf("test2空间利用率:%.2lf\n\n",(double)(sizeof(double)+2*sizeof(char))/(double)sizeof(struct test2)); printf("sizeof(struct test3):%d\n",sizeof(struct test3)); printf("offsetof(struct test3,c):%d\n",offsetof(struct test3,c)); printf("test3空间利用率:%.2lf\n\n",(double)(sizeof(double)+2*sizeof(char))/(double)sizeof(struct test3)); /*验证结论猜想是否正确*/ printf("sizeof(struct test4):%d\n",sizeof(struct test4)); printf("offsetof(struct test4,c):%d\n",offsetof(struct test4,c)); printf("test4空利用率:%.2lf\n\n",(double)(sizeof(double)+2*sizeof(int))/(double)sizeof(struct test4)); system("PAUSE"); return 0;}
- PAINTSTUCT结构体浅析
- 结构体浅析
- 浅析task_struct结构体
- 浅析task_struct结构体
- 浅析task_struct结构体
- 浅析结构体
- C#结构体的特点浅析
- MYSQL源码分析之结构体浅析
- 结构体对齐的几个问题浅析
- libevent源码浅析: 主要的结构体
- linux信号 - sigaction结构体浅析
- sizeof 浅析-----求结构体大小
- libevent源码浅析: 主要的结构体
- 浅析C#中的结构体和类
- C++结构体占用内存大小浅析
- sizeof浅析,求结构体大小
- 浅析Linux下的task_struct结构体
- 浅析C++的结构体与容器
- POJ 1785 Binary Search Heap Construction (线段树)
- java 文件读写的实用工具
- Sqlplus 常用命令
- MySQL cluster 7.X集群部署配置
- java Log4j 配置说明
- 结构体浅析
- 高数上1-3
- Linux/Unix shell 参数传递到SQL脚本
- SQLiteDatabase 增删改查参数说明
- Spring整合freemarker发送邮件
- 求大神给一些关于Jquery Hibernate 等等相关资料和小案例
- SQLPlus命令详细说明
- 在Hadoop分布式集群环境下Mahout安装和运行K-means、协同过滤实例
- 函数指针