C中结构体等总结

C中结构体、共用体、枚举总结

Posted by Anriku on March 23, 2018

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中结构体、共用体、枚举基本的使用应该是没有问题了的。

转载请注明链接