不同过程之间,使用自定义消息,可否传递struct ifreq 结构体结构体

C语言:不同文件之间结构体数组参数传递_O行到水穷处O坐看云起时O_新浪博客
C语言:不同文件之间结构体数组参数传递
在C语言的学习过程中,结构体数组参数传递是一个常见的问题,举个最简单的例子,我们每个学习C语言的人都会接触到的:课程结束的时候的学生成绩管理系统的,如果想要把成绩保存到一个文件中并且每次都能修改文件内的信息的话就比较麻烦。
这个课程设计如果做成一个.c的文件其实并不难,都是C的基础语言,如果做成多个文件就要牵涉到数据的传送。
C语言函数传递数据的时候,传送的形参其本身并不是直接把数据直接传送到别的文件函数,而是把原来的数据复制一下传送过去如果不返回值的话所有的操作就只是操作,对原来的数据并没有改变,如果你想对main函数里面传送的数据直接进行修改的话,这个时候直接传递参数实不可取的,当然你返回值给一个同样结构体数组格式的也是可以的。当然还有另一种解决方式就是传送数据指针,这样的话所有别的文件的操作是针对指针所做的操作那直接改动数据最后主函数直接调用也是可以的比如:
1.首先在stud.h文件中先把学生的结构体写好。然后,声明函数:
typedef struct student{
& & & char
void studentchange(studd
*stu1);//参数指针传递的时候一定要记好形式,这个时候不能再用struct
、sudent去定义参数,而是用结构体名字studd来定义参数指针,因为这个指针是针对这个结构体的,而不是这个结构体的属性struct或者他的tag(标识)student!!!,并且这里的stu1在这里只是一个形式参数,只是为了说明函数调用的时候这个地方是一个结构体数组而已,没有实际意义。
2.然后在main.c函数中把主函数写好:
#include"stud.h"
&stu[20];//构造一个结构体数组
& &stu[1].marks=99;
& &stu[2].marks=89;
&stu[1].name[10]="abc";//随便赋几个值目的是为了演示结构体数组参数传递;
&studentchange(stu);//stu在这里是地址,是结构体数组的地址,传递地址直接操作
&printf("%d&&&&&&&&&",stu[1].marks);//测试演示在student.c中函数修改数据之后指针所指向的数据在此调用的时候已经发生改变,
3.然后在student.c文件中详细说明函数的操作:
void &studentchange(studd
*stu1)​
printf("%d&&&&&&&&&",stu1[1].marks);
printf("%s&&&&&&&&&",stu[1].name);​//这两个printf目的是输出main函数中的数据信息,演示一下整个函数调用的时候是成功的
& stu1[1].marks=1;
O行到水穷处O坐看云起时O
博客等级:
博客积分:0
博客访问:5,156
关注人气:0
荣誉徽章:第10章 结构型、共用型、枚举型及用户自定义型数据_其它编程-织梦者
当前位置:&>&&>& > 第10章 结构型、共用型、枚举型及用户自定义型数据
第10章 结构型、共用型、枚举型及用户自定义型数据
花费一个下午和一个晚上我抄了这么多东西,那么我有怎用的收获呢?日
我总是抄这些知识点是个坏习惯。。。需要想办法解决
数组、变量一旦定义以后只能存储定义的类型数据
一个结构体变量可以包含不同的数据类型的数据
结构体类型是C语言中最重要的构造数据类型。
结构体类型概念及其应用
共用体类型
结构体数组
结构体指针
typedef定义
10.1 结构体类型
结构体类型简介
结构体类型是不同类型数据的集合,它是用户自己定义的数据类型。
(1)结构体中可以包含不用类型的数据,数组只能包含同一类型的数据
(2)结构体可以相互赋值,而数组不能直接相互赋值。因为结构体类型本身是数据类型,而数组是同一类型数据的集合。
10.1.2 结构体类型定义
在C语言中,一个学生的信息可以用如下结构体保存:
char name[10];
char[sex];
上述语句定义一个结构类型s,s为结构体名,大括号中为一个结构体包含的成员
字符型数组
字符型变量
结构体定义形式如下:
struct 结构体名
结构体成员
结构体成员可以是变量、数组、指针、等数据类型,定义了结构体之后,就可以用它来声明结构体变量。
结构体变量声明以后,即可引用结构体中的成员。
结构体变量的定义方式有以下三种:
(1)先定义结构体,后定义结构体变量。
char name[10];
struct s s1,s2;
通过结构体S定义了两个结构体变量s1和s2,程序可以直接引用两个结构体变量中的成员。
(2)定义结构体同时定义结构体变量
char name[10];
在定义结构体的同时定义了两个结构体变量s1和s2;
(3)只定义结构体变量
char name[10];
没有定义结构体类型名,直接定义了两个结构体变量s1和s2,因为没有定义结构体类型名,因此除了直接定义,不能使用其他方式定义定义结构体变量。
(1)结构体是用户自定义类型,结构体可用来定义结构体变量,但不能用来传递信息。
(2)结构体中可以嵌套另外一个结构体,即一个结构体中可以包含多个结构体。
struct time
struct data
在结构体中嵌套了结构体,通过结构体可以用来调用结构体中的成员
10.1.3 结构体类型引用
定义结构体变量之后,可以通过操作符’.‘来引用结构体中的成员。
结构体成员的引用方式:  结构体变量名.成员名;
char name[10];
结构体大括号后的分号为结构体定义基本形式,若没加上则会出错。
范例10.1:从键盘上输入一个学生的信息,将这些信息存储至结构体中并输出。
分析:定义一个结构体,包含学生的一些基本信息,然后对结构体进行赋值,最后输出结构体中的成员。
#include &stdio.h&
void main()
char name[10];
//定义结构体类型变量s1
printf("输入学生姓名:");
gets_s(s1.name);
printf("输入学生的性别:");
s1.sex=getchar();
printf("输入学生岁数:");//从键盘获取字符串保存至结构体相应的变量中
scanf("%d",&s1.age);
printf("输入学生的分数:");
scanf("%f",&s1.score);
printf("年龄:%s\n",s1.name);
printf("名字:%s\n",s1.age);
printf("性别:%c\n",s1.sex);//输出这些信息至屏幕上
printf("分数:%f\n",s1.score);
10.1.4结构体变量初始化
结构体变量与变量相似,在定义结构体变量的同时便可对其各个成员赋初始值,即结构体变量的初始化。
结构体变量的初始化与定义类似:
(1)第一种方式:
char name[10];
struct s s1={'lihai',20,'M',90.5}
(2)第二种方式
char name[10];
}s1={'lihai',20,'M',90.5};
不能在结构体内部进行初始化
char name[10] ="LiHai";
int age = 20;
char sex ='M';
float score =90.5;
10.2 结构体数组
结构体数组定义
结构体定义形式与数组定义形式类似:
(1)先定义结构体,后定义结构体数组
char name[10];
struct s a[10];
(2)定义结构体的同时定义结构体数组
char name[10];
定义了包含10个元素的结构体数组,每一个结构体元素占据17个字节,其中字符型数组占10个字节,整形变量占2个字节,字符型变量占1个字节,浮点型变量占4个字节
结构体数组引用
结构体数组定义以后,通过下标即可引用相应的结构体元素。
范例10.2现有3个候选人,10个人进行投票,统计每一个候选人的票数。
分析:将这3个候选人定义为结构体类型,10个人进行投票,将每个人的投票与结构体中的名字进行比较,若相等则其票数加1,最后输出3个候选人的票数。
#include &stdio.h&
#include &string.h&
char name[10];
}p[3] = {"zhang",0,"li",0,"hu",0};
void main()
char n[10];
for (i = 0; i & 10; i++)
scanf("%s",n);
for (j = 0; j & 3; j++)
if (strcmp(n, p[j].name) == 0)
printf("最终的结果:\n");
for (j = 0; j & 3; j++)
printf("%s:%d票\n",p[j].name,p[j].c);
#  10.2.3 结构体数组的初始化
结构体数组可以在定义时就赋予初值,即进行初始化。结构体数组初始化方式有两种。
(1)初始化数组所有元素
char name[10];
}s[3]={{"Zhang lin",20,80.5},{"Li Tao",19,89.0},{"Xiu Yan",21,90.0}};
定义一个包含三个元素的结构体数组,并对其中所有元素进行了初始化。
(2)初始化数组部分元素,且结构体中嵌套另一个结构体。
struct Time
struct Data
{6,56,34,()},
{7,35,56,()};
10.3 结构指针
结构指针指向已定义的结构体变量在内存中的首地址,从而对地址中的内容进行操作。
结构体指针概念及其定义
结构体指针可以指向结构体变量的首地址,其定义形式如下:
结构体类型 *指针名
char name[10];
struct st *p;
定义一个结构体st的指针P,但其值是不确定的。通过以下语句可将结构体变量s的地址赋给p,使p指向结构体变量
其中‘&’为取地址符,&s表示结构体变量S的地址。指针赋值后,通过指针即可访问结构体中的成员。
(*p).name
括号不能省去,因为”.“的优先级比”.“高。
在C语言中通过指针还可以用另外一种方式来访问结构体成员,即使用运算符”–&“
p --& name
结构体数组指针
结构体数组也可以定义指针,通过指针对其进行操作
(1)(++p)-&num和(p++)–&num的区别
先使P的值加1,使P指向数组的下一个元素,再访问该元素的结构体成员num
先访问元素的结构体成员num,再使p的值加1,指向下一个元素。
(2)结构体数组指针P指向数组有以下三种方式
结构体指针应用
gets_s函数不接受一个参数
double
printf 格式字符串需要类型char的参数,但可变参数1拥有了类型double
#include &stdio.h&
#include &stdlib.h&
char name[10];
char age[5];
char sex[6];
}s;//结构体变量s
void main()
struct st *p = &s; //定义结构指针
char a[20];
printf("输入名字:");//实现结构成员的数据输入
gets_s(p-&name);
printf("输入年龄: ");
gets_s(p-&age);
printf("输入性别: ");
gets_s(p-&sex);
printf("输入分数: ");
//gets_s(s);
//p-&score = atof(s);//该函数的功能是将字符型数据转化为浮点型数据
printf("名字:%s\n",p-&name);
printf("性别:%s\n",p-&sex);
printf("年龄:%s\n",p-&age);
printf("分数: %s\n",p-&score);
结构与函数参数
结构体可以用来作为函数的参数
10.4.1 结构体变量作为函数参数
将结构体变量作为实参传递给一个函数
将结构体变量的值传递给函数,即传值调用
范例10.7 编写一个程序,将结构体变量作为实参传递给其他的函数,
分析:结构体变量直接传递给函数,是传值调用,因此函数内形参值的变化不会影响实参的值。
#include &stdio.h&
#include &stdlib.h&
char name[10];
char age[5];
char sex[6];
void out(st stu)//自定义函数
printf("名字:%s\n",stu.name);//输出结构体成员
printf("性别:%s\n",stu.sex);
printf("年龄:%s\n",stu.age);
printf("分数:%s\n",stu.score);
void in(st stu)
char score[10];
printf("输入名字: ");//从键盘获取字符串至stu.name
gets_s(stu.name);
printf("输入年龄: ");
gets_s(stu.age);
printf("输入性别: ");
gets_s(stu.sex);
printf("输入分数: ");
gets_s(score);
stu.score = atof(score);
out(stu);//调用OUT()函数输出学生信息
void main()
struct st s =
{"LiMing","20","man",87.5};
out(s);//调用in()函数
虽然in()函数中对结构体变量重新进行赋值,但由于传递方式为传值调用,因此不会影响主函数main()中结构体变量的值。
10.4.2 结构体地址作为函数参数
将结构体变量地址作为参数传递给函数,则形参应为相同类型的指针,这种方式为传址方式,因此函数内结构体变量值的变化会影响实参。
范例10.8 编写一个程序,将结构体变量的地址作为实参传递给其他的函数
分析:结构体变量地址传递给函数,是传址调用。因此形参值的变化不会影响实参值。
#include &stdio.h&
#include &stdlib.h&
char name[10];
char age[5];
char sex[6];
void out(st stu)
printf("名字: %s\n",stu.name);
printf("性别: %s\n",stu.sex);
printf("年龄: %s\n",stu.age);
printf("分数: %s\n",stu.score);
void in(st *stu)
char score[10];
printf("输入名字:");
gets_s(stu-&name);
printf("输入性别:");
gets_s(stu-&sex);
printf("输入分数:");
gets_s(score);
stu-&score = atof(score);
void main()
struct st s = { "Li maing","20","man",87.5};
10.4.3 结构体数组作为函数参数
数组名可以代表数组的首地址。结构体数组可以作为参数传递给函数,即将结构体数组的首地址传递给函数。
范例10.9 编写一个程序,将结构体数组作为实参传递给其他的函数。
分析:结构体数组传递给函数,即将结构体数组首地址传递给函数,然后便可以对数组中的内容进行操作。
#include &stdio.h&
#include &stdlib.h&
char name[10];
char age[5];
char sex[6];
void prin(st s[])
for (i = 0; i & 3; i++)
printf("名字:%s\n",s[i].name);
printf("年龄:%s\n",s[i].age);
printf("性别: %s\n",s[i].sex);
printf("分数:%s\n",s[i].score);
void main()
struct st s[3] = {
{"Li Ming","20","man",87.0},
{"Hu Su","19","women",89.0},
{"Jun Yi","21","man",90.5}
10.5共用体
都是将不同的数据类型组合在一起,共用体与结构体所占的空间不同
10.5.1 共用体概念及其定义
共用体为用户自定义构造类型
结构体类型存储时采用覆盖方式,即后一个类型的数据会覆盖前一个类型数据。
结构体变量所占空间为所有成员占据的空间之和。
共用体变量所占空间为成员中所占空间最大的成员字节数。
共用体定义形式如下:
}共用体变量名;
成员指针运算符
成员选择运算符
结构体与共用体的区别:
对共用体变量进行操作,可以通过’.‘和 ’-&‘运算符来实现。若操作对象为共用体变量,则用”.“运算符。若操作对象为共用体类型指针,则使用”-&”运算符。
- (1)结构体成员都有自己的存储空间。结构体变量所占存储空间为各个成员所占存储空间之和
共用体变量所占存储空间为各个成员中占存储空间最大的成员的字节数。
- (2)结构体变量可以同时对其所有成员赋值,
共用体类型不能同时对所有的成员赋值,只能单独赋值
- (3)结构体变量可以初始化,
共用体在定义时不能赋值
10.5.2 共用体变量应用
要引用共用体变量中的成员,可以通过共用体变量来引用,也可以通过共用体指针来引用。
(1)共用体变量的值为最后一次赋的值
最后一个共用体变量t的值为4.5,前面两个值都被覆盖。
(2)共用体变量在定义时不能赋值
如何定义共用体变量?
}t={'z',4,9.0};
上述程序是错误的
(2)不能对共用体变量整体进行赋值。
最后两行都是错误的
(4)与结构体类似,可以定义数组
范例10.10:通过下面的例子,了解共用体的存储过程
分析:共用体是用户自定义类型,是不同数据类型的集合。
#include &stdio.h&
void main()
printf("sizeof(s.x)=%d\n",sizeof(s.x));
printf("sizeof(s.y)=%d\n",sizeof(s.y));
printf("sizeof(s.z)=%d\n",sizeof(s.z));
printf("sizeof(s)=%d\n",sizeof(s));
10.5.3 共同体与结构体的嵌套
C语言中,结构体还可以与共用体嵌套使用
范例10.11 编写一个程序,实现结构体与共用体的嵌套使用。
结构体可以嵌套共用体,共用体也可以嵌套结构体。当要引用其中的成员时,可以通过”.“或者”-&”
#include &stdio.h&
void main()
struct std
s.a.m = s.x*s.y;
s.a.n = s.y - s.x;
printf("结果:%d,%d\n",s.a.m,s.a.n);
现假设有若干人的信息要记录,其中包括学生和老师。学生的信息包括姓名、性别、编号、职业、平均成绩,老师的信息包括姓名、性别、编号、职业、任课科目,编写一个程序,从键盘上输入数据,并将结果输出至屏幕。
#include &stdio.h&
char n[10];
char num[20];
char course[10];
void main()
for (i = 0; i & 3; i++)
scanf("%s %c %c",&s[i].n,&s[i].sex,&s[i].num,&s[i].j);
if (s[i].j == 's')
scanf("%f", &s[i].a.score);
scanf("%f",&s[i].a.course);
for (i = 0; i & 3; i++)
if (s[i].j == 's')
printf("%s,%c,%s,%c,%f\n", s[i].n, s[i].sex, s[i].num, s[i].j, s[i].a.score);
printf("%s,%c,%s,%c,%s\n", s[i].n, s[i].sex, s[i].num, s[i].j, s[i].a.course);
10.6 枚举类型
enum 枚举类型名(枚举元素表)
color(red,blue,green,white,black);
enum为关键字,color为枚举类型名,
red 、blue green white 和black为枚举元素
定义了枚举类型后,可以用来定义枚举类型的变量
color a,b;
定义了两个**枚举类型变量**a和b,其取值范围在枚举元素之内,只能为其中的某一个值。
枚举类型具有以下4个特点。
(1)枚举元素为常量,从起始位置开始值为0,1,2。。。
enum color(red,blue,green,white,black);
printf("%d",c);
输出结果为2,因为green在枚举元素的第三个位置,因此其默认值为2.
(2)枚举元素为常量,不能赋值,但可以在定义时进行赋值
enum color(red,blue,green,white,black);
green = 0;
上述程序是错误的,编译时将会出错
(3)枚举常量可以用来进行比较
if(c&white)
因为枚举元素都有一个默认值,因此可将枚举类型变量的值与枚举元素进行比较。
(4)枚举类型不能直接进行赋值,但可以强制转化进行赋值。
c = (enum color)4;
将数字强制转化再进行赋值,是正确的
范例10.13 现有红、黄、蓝、绿、白5中颜色,从中取出两个球,打印出所有可能的结果。
#include &stdio.h&
void main()
enum color { red, yellow, blue, green, white };
enum color i,
for (i = i &= i++)
for (j = j &= j++)
if (i != j)
printf("%d ,%d\n", i, j);
//枚举类型上的此操作需要适用于用户定义的运算符函数
二进制“++”:“main::color”不定义该运算符或到预定义运算符可接收的类型的转换
10.7 用户自定义类型
C语言中可以用关键字typedef为已有类型重新定义名称,其定义形式如下:
类型名 标识名
其中类型名可以为C语言中的任意类型,标识名为用户自己命名的名字。
int integer
上述程序用integer表示int类型。
定义变量的方式是等价的,都表示定义一个整型变量
10.14 编写一个程序,通过typedef自定义类型
分析:typedef关键字自定义类型,但它不是创建一个新的类型,而是将已有的类型用新的标识符来表示。
#include &stdio.h&
typedef union
//通过typedef自定义类型
float b[5];
char c[5];
void main()
//通过自定义类型定义变量
printf("共用体所占空间:%d\n",sizeof(x));
//本例用typedef 自定义类型
//通过关键字typedef为共同体类型定义了一个新的标识符
//利用新定义的标识符定义变量
链表是C语言中重要的数据结构,常常被用来处理大量数据。虽然数组也可以用来存储大量的数据,但数据必须要先声明其大小才能使用。在程序的执行过程中不能改变数组的大小,因此定义时一般将数组定的很大,这样往往会造成存储空间的浪费。
链表是一种动态的存储结构,她可以根据实际情况改变内存空间的大小。若需要则临时开辟存储空间,不需要则释放存储空间,这样可以很好地解决存储空间浪费的问题。
链表是很复杂的数据结构,
10.8.1单向链表
单向链表是有若干个结点组成的,每个结点是有数据区域和指针区域两个部分组成的。
数据区域用来存放用户需要存储的数据,
指针区域用来存放下一个结点的地址,便于寻找下一个结点
链表中一般都有一个头结点head,用来指向链表的第一个结点,即整个链表的首地址。
链表中的最后一个结点中指针区域值为空,即NULL,作为链表的结束标志。
数组的存储空间是连续的,而链表是根据实际情况动态申请内存的,因此其存储空间不是连续的。单项链表的示意结构
单向链表每一个结点中的指针区域必须存放下一个结点的地址,才能寻找到下一个结点,否则将不能寻找到下一个结点。
单向链表的每一个结点数据结构定义形式如下:
struct node
struct node *
定义一个结点类型node,通过该标识符可以定义变量,
指向struct node 类型的指针next
通过下面的例子,简单了解链表的概念
分析:单向链表的存储是单向的,其存取必须按照顺序进行。每个结点指针区域应存放下一个结点的地址,只有最后一个结点的指针区域为空。
#include &stdio.h&
char name[10];
struct st * //结构体类型指针
void main()
struct st s1 = { "wanghu",,NULL };//定义结构体变量s1并进行初始化
struct st s2 = { "liuli",,NULL };
struct st s3 = { "Hutao",,NULL };
struct st s4 = { "Yuyan",,NULL };
struct st *
//定义结构体头指针
head = &s1;
//使head指向结构体s1
s1.next = &s2;
//使s1中next指针指向结构体s2
s2.next = &s3;
s3.next = &s4;
s4.next = NULL; //使s4中next指针为空
struct st *p = NULL; //定义结构体指针指向链表头结点
while (p != NULL)//通过while循环输出所有结点
printf("%s,%d,%.lf\n",p-&name,p-&n,p-&score);
定义了一个链表的结点类型
其中包括三种数据级一个指向结构体的指针
定义4个结点并对其初始化
定义一个头结点,用来指向第一个结点
将第一个结点S1的地址赋给头结点,后一个结点的地址赋给前一个结点的指针域,最后一个结点的指针赋值为空
10.8.3 双向链表
双向链表包含有两个指针。单向链表只有一个指针,指向下一个结点,因此要在单向链表中寻找一个结点,只能从开始的位置逐个往下寻找,
双向链表中包含有两个指针,分别指向前驱和后继,因此可以从该链表中的任一结点出发来寻找某一结点,可以很方便地访问一个结点的前驱和后继
双向链表的定义形式如下:
struct node
struct node *
struct node *
上述程序定义了一个双向链表结点类型,其中包含三个部分,数据域data,指向结点前驱指针pre和后向结点后继指针next。
10.17 编写一个程序,实现双向链表的输入、输出。
#include &stdio.h&
#include &malloc.h&
typedef struct node
struct node *
struct node *
void create(link *l)
(*l) = (link)malloc(sizeof(node));
(*l)-&pre = *l;
(*l)-&next = NULL;
printf("输入链表的大小: ");
scanf("%d",&n);
for (i = 1; i &= i++)
p = (link)malloc(sizeof(node));
printf("输入数据: ");
scanf("%d",&p-&data);
p-&next = NULL;
void prin(link l)
printf("%d ",l-&data);
void main()
create(&L);
定义了双向链表结点类型名node和类型指针link.
自定义函数create()通过该函数来创建双向链表
通过while循环判断下一个结点是否为空来输出链表中的结点。
10.8.4 链表中插入结点和删除节点
修改10.17,实现链表中的结点的插入和删除功能。
分析:要插入一个结点,首先应明确其要插入的位置,可通过改变相邻位置结点指针域的值来实现结点的插入。
要删除一个结点,也可以通过改变指针域来实现。
#include &stdio.h&
#include &malloc.h&
typedef struct node
struct node *
void create(link *l)
(*l) = (link)malloc(sizeof(node));
(*l)-&next = NULL;
printf("输入链表的大小: ");
scanf("%d", &n);
for (i = 0; i & i++)
p = (link)malloc(sizeof(node));
printf("输入数据: ");
scanf("%d", &p-&data);
p-&next = NULL;
void insert(link *l)
link p = *l,
printf("输入要插入结点的位置: ");
scanf("%d", &n);
printf("输入要插入结点的值: ");
scanf("%d", &e);
for (i = 1; i & i++)
s = (link)malloc(sizeof(node));
s-&next = p-&
void idelete(link *l)
link p = *l,
printf("输入要删除结点的位置: ");
scanf("%d", &n);
for (i = 1; i & i++)
p-&next = s-&
void prin(link l)
printf("%d ", l-&data);
printf("\n");
void main()
create(&L);
insert(&L);
自定义函数insert().该函数的功能将一个结点插入至链表的指定位置,形成一个新的链表。
自定义函数prin(),此函数用来删除链表上特定位置上的结点,从而实现删除结点的功能。
以上就是第10章 结构型、共用型、枚举型及用户自定义型数据的全文介绍,希望对您学习和使用程序编程有所帮助.
这些内容可能对你也有帮助
更多可查看其它编程列表页。
猜您也会喜欢这些文章安全检查中...
请打开浏览器的javascript,然后刷新浏览器
< 浏览器安全检查中...
还剩 5 秒&用户名:telesli1013
文章数:16
访问量:18357
注册日期:
阅读量:1297
阅读量:3317
阅读量:582745
阅读量:467638
51CTO推荐博文
Struct结构体是C/C++语言中用来自定义数据类型的,
我们学习结构体知识,除了学习一些相关的基本知识外,我们必须了解其在计算机内部具体的存在,主要问题集中在结构的大小以及内存的分配问题
一、字节对齐
现代计算机中内存空间都是按照byte划分的,从理论上讲似乎对任何类型的变量的访问可以从任何地址开始,但实际情况是在访问特定类型变量的时候经常在特定的内存地址访问,这就需要各种类型数据按照一定的规则在空间上排列,而不是顺序的一个接一个的排放,这就是对齐。我们拿32位系统来说(以下内容均对于32位系统),按我的理解比如一个char型变量c之后我们接着需要存储一个int型的变量i假如c变量的首地址是0x0044ff33,那么变量i虽然一定存储在0x0044ff33之后,但是其首地址一定不会是0x0044ff34,而会是0x0044ff38,因为这样对于计算机的内部处理将更加的方便和快捷。
二、结构体大小及内存分配
我们举两个例子来讨论:
1、struct&Demo
&&&&&&&&&&&char&c;
&&&&&&&&&&&int&i;
&&&struct&Demo&demo1;
那么我们提出问题:sizeof(demo1)&=&?
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&demo1&=&?
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&demo1.c&=&?
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&demo.i&=&?
答案:&&&&&&&&&&&&&&&&&&&sizeof(demo1)&=&8&字节
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&demo1&=&0x0022ff48
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&demo1.c&=&0x0022ff48
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&demo1.i&=&0x0022ff4c
根据编译器的不同,对于地址空间:0x0022ff48&0x0022ff4c做不同处理,有的填充随机字符(如VC,会在这里填充CC&CC&CC),而有的编译器也有不同处理,比如填0或者空着
2、struct&Demo
&&&&&&&&&&&int&i;
&&&&&&&&&&&char&c;
&&&&&&&&&&&int&&j;
&&&struct&Demo&demo2;
那么我们提出问题:sizeof(demo2)&=&?
&&&&&&&&&&&&&&&&&&&&&&&&&demo2&=&?
&&&&&&&&&&&&&&&&&&&&&&&&&demo2.i&=&?
&&&&&&&&&&&&&&&&&&&&&&&&&demo2.c&=&?
&&&&&&&&&&&&&&&&&&&&&&&&&demo2.j&=&?
答案:&&&&&&&&&&&&&sizeof(demo2)&=&12&字节
&&&&&&&&&&&&&&&&&&&&&&&&&demo2&=&0x0022ff44
&&&&&&&&&&&&&&&&&&&&&&&&&demo2.i&=0x0022ff44
&&&&&&&&&&&&&&&&&&&&&&&&&demo2.c&=&0x0022ff48
&&&&&&&&&&&&&&&&&&&&&&&&&demo2.j&=0x0022ff4c
根据编译器的不同,对于地址空间:0x0022ff48&0x0022ff4c做不同处理,有的填充随机字符(如VC,会在这里填充CC&CC&CC),而有的编译器也有不同处理,比如填0或者空着
3、struct&Demo
&&&&&&&&&&&int&i;
&&&&&&&&&&&char&c;
&&&struct&Demo&demo3;
那么我们提出问题:sizeof(demo3)&=&?
&&&&&&&&&&&&&&&&&&&&&&&&&demo3&=&?
&&&&&&&&&&&&&&&&&&&&&&&&&demo3.i&=&?
&&&&&&&&&&&&&&&&&&&&&&&&&demo3.c&=&?
答案:&&&&&&&&&&&&&sizeof(demo3)&=&12&字节
&&&&&&&&&&&&&&&&&&&&&&&&&demo3&=&0x0022ff44
&&&&&&&&&&&&&&&&&&&&&&&&&demo3.i&=&0x0022ff44
&&&&&&&&&&&&&&&&&&&&&&&&&demo3.c&=&0x0022ff48
根据编译器的不同,对于地址空间:0x0022ff49&0022ff4c做不同处理,有的填充随机字符(如VC,会在这里填充CC&CC&CC),而有的编译器也有不同处理,比如填0或者空着这与上面两个不同,因为缺口在后面,但是本质意义是相同的。、
其实字节对齐的细节和具体编译器实现相关,但一般而言,满足三个准则:&
1)&结构体变量的首地址能够被其最宽基本类型成员的大小所整除;& 
2)&结构体每个成员相对于结构体首地址的偏移量都是成员大小的整数倍,如有需要编译器会在成员之间加上填充字节;例如上面第一结构体变量的地址空间。&
3)&结构体的总大小为结构体最宽基本类型成员大小的整数倍,如有需要编译器会在最末一个成员之后加上填充字节。例如上面第三结构体变量。
本文出自 “” 博客,请务必保留此出处
了这篇文章
类别:┆阅读(0)┆评论(0)}

我要回帖

更多关于 struct stat结构体 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信