c语言的自定义类型

c语言的自定义类型分为:结构体 枚举 联合,下面分别介绍一下他们的特点.

结构体:

1. 结构体的类型声明

struct tag
{
    member__list;
}variable__list;

例如描述一个学生:

struct stu{
    char name[20];
    int age;
    char sex[5];
    char id[20];
};

特殊的申明:
在声明结构体的时候,可以不完全的声明。
eg:

struct{
    int a ;
    char b;
    float c;
}x;
struct{
    int a;
    char b;
    float c;
}a[20],*p;

上面的两个结构体在声明的时候省略了结构体标签(tag)。

2. 结构的成员

  • 结构体变量访问成员 结构体变量的成员是通过点操作符(.)访问的,点操作符接受两个操作数。例如:
  • 这里写图片描述
    我们可以看到s有成员name和age;
    那我们如何访问s的成员?
struct S s;
strcpy(s.name,"zhangsan");
s.age=20;

3. 结构的自引用
结构体的引用方式:

struct Node{
    int data;
    struct Node* next;
}

4. 结构的不完整声明

struct B;
struct A;
{
    int a;
    struct B* pb;
};
struct B
{
    int b;
    struct A* pa;
};

5. 结构体变量的定义和初始化

struct point{
    int x;
    int y;
}p1;                      //声明类型的同时定义变量p1
struct Point p2;          //定义结构体变量p2   

//初始化:定义变量的同时赋初值。
struct Point p3={x,y};

struct Stu{                     //声明类型
    char name[15];
    int age;
};
struct Stu s={"zhang san",20};  //初始化

6. 结构体的内存对齐

结构体内存对齐的规则:

  • 结构体第一个成员不需要对齐,在结构体变量偏移为0的地址处,但它也有对齐数
  • 除了第一个成员,其他的成员都需要对齐到对齐数的整数倍(VS:8 —— Linux: 4
  • 结构体的总大小为最大对齐数的整数倍
  • 如果嵌套了结构体,嵌套的结构体对齐到自己最大对齐数的整数倍,结构体的总大小就是整天最大对齐数的整数倍。
    为什么存在内存对齐?
  • 平台的不同,硬件访问内存的要求 (平台原因)
  • 为了减少访问内存的次数,使用多点内存,使效率提高(性能原因)

总体来说:
结构体的内存对齐是拿空间来换取时间的做法。
7. 结构体的传参
如果传递一个结构体对象的时候,结构体过大,参数压栈的系统开销比较大,多一会导致性能的下降。
所以结构体传参的时候,要传结构体的地址。
8. 结构体实现位段
位段的声明和结构体是类似的,有两个不同:

  1. 位段的成员必须是int unsigned int或 signed int。
  2. 位段的成员名后边有一个冒号和一个数字。

位段的内存分配
1. 位段的成员可以是类型int unsigned int signed int 或者char类型。
2. 位段的空间上按照需要以4个字节(int)或者1个字节(char)的方式来开辟的。
3. 位段涉及很多不确定因素,位段是不跨平台的,注重可移植的程序应该避免使用位段。
eg:

struct S
{
    char a:3;
    cahr b:4;
    char c:5;
    cahr d:4;
};
struct S s={0};
s.a=10;
s.b=12;
s.c=3;
s.d=4;

位段的跨平台问题

  • int位段被当成有符号数还是无符号数是不确定的。
  • 位段中最大位数目不能确定。
  • 位段中的成员在内存中从左向右分配,还是从右向左分配标准尚未定义
  • 当一个结构包含两个位段,第二个位段成员比较大,无法容纳于第一个位段剩余的位时,是舍弃剩余的位还是利用的,这是不确定的。

总结:

跟结构相比,位段可以达到同样的效果,但是可以很好的节省空间,但是跨平台的问题存在。

枚举:

枚举就是一一列举,枚举的定义:

enum Day{
    Mon,
    Tues,
    Wed,
    Thur,
    Fri,
    Sat,
    Sun,
};
enum Sex{
    MALE,
    FEMALE,
    SECRET
};

以上enum Day,enum Sex都是枚举类型。
{}中的内容是枚举类型的可能取值,也叫“枚举常量”。这些可能取值都是有值的,默认从0开始。
枚举的优点:
1.增加代码的可读性和可维护性
2.和#define定义的标识符比较枚举有类型检查,更加严谨
3.防止了命名污染(封装)
4.便于调试
5.实用方便,一次可以定义多个常量

联合

联合类型的定义:
联合也是一种特殊的自定义类型这种类型定义的变量也包含一系列的成员,特征是这些成员公用同一块空间。
eg:

union Un{                 //联合类型的声明
    char c;
    int i;
};                           //联合变量的定义
union Un un;                 //计算联合变量的大小
printf("%d\n",sizeof(un));

联合的特点:
联合的成员是共用同一块内存,其大小至少是最大成员的大小。
联合体大小的计算:

  • 联合的大小至少是最大成员的大小
  • 当最大成员大小不是最大对齐数的整数倍的时候,就要对齐到最大对齐数的整数倍。

猜你喜欢

转载自blog.csdn.net/xy294636185/article/details/80352948