C语言众所周知是一门面向过程的语言,没有类相关的东西。但是它可以用结构体来作为一个相当于只有成员变量的一个类。说到结构体又不得不谈谈共用体和枚举了。因此,今天有三个主要的内容,那就是结构体
、共用体
、枚举
。
结构体
结构体是相当于面向对象语言中的类的简易版的东西。可以完成脱离语言中变量类型,来进行自定义变量类型的一个东西。结构体通过struct关键词来进行定义。
结构体的定义及变量的初始化
第一种模版情况(通过struct 结构体名
来定义变量)
struct 结构体名{
数据类型1 变量1;
数据类型2 变量2;
...
数据类型n 变量n;
};
//如:
struct Student{
long StudentID;
char studentName[10];
char studentSex;
};
//变量定义及初始化
struct Student st = {2016215039,"Anriku",'M'};
第二种模版(直接定义变量)
struct 结构体名(可要可不要){
数据类型1 变量1;
数据类型2 变量2;
...
数据类型n 变量n;
}结构体变量名;
//如
struct{
long StudentID;
char studentName[10];
char studentSex;
}st;//student是一个变量
//初始化变量
st = {2016215039,"Anriku",'M'};
第三种模版(重新定义结构体类型名,通过别名来定义变量)
typedef struct 结构体名(可要可不要){
数据类型1 变量1;
数据类型2 变量2;
...
数据类型n 变量n;
}重新定义的数据类型名;
//如:
typedef struct{
long StudentID;
char studentName[10];
char studentSex;
}STDENT;//这里注意在C中,通过typedef定义的别名一般是大写的
//变量定义及初始化
STDENT st = {2016215039,"Anriku",'M'};
结构体变量的地址
结构体变量的地址是结构体变量所占内存空间的
首地址,而结构体成员地址值与结构体成员
在结构体中所处的位置及该
成员所占内存的字节数`相关。
来张图吧:
结构体所占内存的字节数(内存对齐)
性能原因:一般为了提高内存寻址的效率,处理器体系结构为特定的数据类型引入了特殊的内存对齐
。为了满足处理器的对齐要求,可能会在较小的成员加入补位
。
平台原因:一些架构的CPU在内存未对齐的时候会发生错误。
struct sample{
char m1;
int m2;
char m3;
};
上面的结构体的在内存中存储的样子就像下图一样:
关于内存对齐的一些更详细的内容,可以参考C/C++内存对齐。
结构体指针及两种引用结构体成员的方式
我们直接以上面第三个模版的代码
作为前提,来进行解释:
//定义一个结构体指针
STUDENT *stu = &st;
//第一种:用结构体变量引用成员的方式:
st.studentName;
//第二种:用指针引用成员的方式
stu->student;
结构传参的两种情况
用结构体变量
作为函数参数,向函数传参。这种方式是进行值传递
的,也就是函数中的形参是传递的实参的一个副本
。改变形参的值不影响实参的值。
//如,我们有一个这样的方法
void doSomething(STUDENT st){
...
}
用结构体指针
作为函数参数,向函数传参。这种方式是进行地址的传递
,因此改变形参的值会影响实参的值。
//如,有下面一个方法
void doSomething(STUDENT *st){
...
}
共用体
共用体
也称为联合(Union)
,是一种在其中的成员变量共用一段内存的构造数据类型。用union关键词
来定义。
共用体类型所占内存空间的大小
取决于其成员中所占内存空间最多的成员变量
。而且共用体当前状态是只会记录一种变量的值(也就是它们的值会进行相互的擦出的)。
下面是一个共用体的定义:
union Something{
int id;
char ch;
}
共用体采用与开始地址对齐的方式进行内存的分配。下面是一个示意图:
共用体的初始化
下面像结构体一样初始化是错误的:
//注意:是错误的
union Something s = {10,'c'};
要想下面一样初始化:
union Something s;
s.id = 1;
//把id给覆盖了
s.ch = 'c';
以上就是共用体和结构体体差别的地方,其它的像重新定义类型名呀,函数传参呀的都是一样的。
枚举
C中的枚举通过enum
来进行定义,在枚举后面通过{}
来定义枚举变量
。枚举变量其实就是整型变量
。
枚举的定义
第一种方式是直接定义,这种方式定义第一个枚举变量的值为0,后面依次递增。就像下面一样:
//yes = 0,no = 1,none = 2
enum Response{
yse,
no,
none
};
第二种方式是为第一个枚举变量进行赋值,后面的变量从这个值开始依次递增。就像下面一样。
//yes = -1,no = 0,none = 1
enum Response{
yes = -1,
no,
none
};
第三种方式是为每一个枚举变量都进行赋值,没有递增。就像下面一样:
//yes = -1,no = 10,none = 3
enum Resposne{
yes = -1,
no = 10,
none = 3
};
其中上面的Response称为是枚举标签
。
以上就是枚举的基本内容,其它的像重新定义类型名呀,函数传参呀的都是一样的。
总结
今天对C中的结构体、共用体、枚举做了一个小小的总结,分析了它们之间的异同。通过今天的总结对C中结构体、共用体、枚举基本的使用应该是没有问题了的。
转载请注明链接