c语言的自定义类型

简介: c语言的自定义类型

一、结构体

1、结构体的声明

如下struct是结构体的声明,里面可以放很多个不同类型的数据,而结构体就是这些值的集合,这些值又称为结构体的成员。

如下面就是利用结构体去设定一个学生的信息,如姓名,年龄这些都不是一样的数据类型,但是可以放在一个结构体类型中,从而去一下定义不同类型的数据了,这样就可以方便使用。

int main()
{
  struct Stu
  {
    char name[20];//姓名
    int age;//年龄
    char sex[5];//性别
    char id[20];//学号
  };
  return 0;
}

还用一种声明就是特殊的声明,如下这种特殊的声明就是省略标签名的声明,只定义成员变量却不定义变量名的声明。

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

2、结构体的自引用

结构体的成员是可以放很多种的类型,所以能不能把结构体放入结构体呢,当然也是可以的,但是不能嵌入同类型的,例如下方代码1这样就是不能使用的。但是可以使用结构体指针,例如代码2就是使用结构体指针使用的嵌套。

如果没有结构体指针的话,他就会一直嵌套停不下来,所以需要一个指针结束,且必须在末尾。

//代码1
struct Node
{
int data;
struct Node next;
};
 
//代码2
struct Node
{
int data;
struct Node* next;
};

3、结构体变量的定义和初始化

既然我们了解什么是结构体的声明和如何嵌套,那么我们可以进行变量的定义和初始化了,如下方代码第一个Point就是一个结构体变量,然后在大括号后面的p1就是在声明结构体变量的同时定义了变量p1,而怕p2就是根据Point这个结构体类型进行定义的第二个结构体变量,这个结构体的成员和p1一样,p3就是在定义p3变量的同时进行赋值,把结构体成员的参数赋值为0。

struct Stu s这个结构体变量的成员中是不同的类型,然后在进行这个变量的传参时,第一个因为时字符类型,然后就赋值了字符串“zhangsan”,年龄是整数,所以就赋值整数。

struct Node n2就是嵌套结构体的赋值,首先把这个结构体本身的data变量赋值10,然后第二个是嵌套的结构体变量,它里面有两个变量,这时需要用大括号引用进行嵌套赋值,最后把结构体指针赋值

为NULL,这就是结构体指针嵌套的赋值。

struct Point
{
int x;
int y;
}p1;
//声明类型的同时定义变量p1
struct Point p2;
//定义结构体变量p2
//初始化:定义变量的同时赋初值。
struct Point p3 = {0, 0};
struct Stu        //类型声明
{
char name[15];//名字
int age;      //年龄
};
struct Stu s = {"zhangsan", 20};//初始化
struct Node
{
int data;
struct Point p;
struct Node* next;
}n1 = {10, {4,5}, NULL};
//结构体嵌套初始化
struct Node n2 = {20, {5, 6}, NULL};//结构体嵌套初始化

4、结构体内存对齐

结构的内存对齐是一个比较难的知识点,在不同的编译环境下也各有不同的默认对齐数,他的对齐规则是从第一个成员开始如下图所示,可以看出第一个是double类型所以和vs的默认对齐数相比,将取最小,然后占用8个字节char类型和默认对齐数相比,1最小所以是1的倍数可以占用从8开始占用一个字节,而int类型是4比默认对齐数小,需要占用4个字节,从4的倍数,开始也就是12开始,所以这个结构体变量占用了16个字节,最后这个地址大小就是这个结构体成员的最大对齐数的倍数。

为什么会有内存对齐?大部分人参考资料是这么说的

1. 平台原因(移植原因): 不是所有的硬件平台都能访问任意地址上的任意数据的;某些硬件平台只能在某些地址处取某些特定类型的数据,否则抛出硬件异常。

2. 性能原因: 数据结构(尤其是栈)应该尽可能地在自然边界上对齐。 原因在于,为了访问未对齐的内存,处理器需要作两次内存访问;而对齐的内存访问仅需要一次访问。

从上图可以看出中间有的字节没有使用,我们也可以使用#pragma 这个指令来进行修改默认对齐数,使得空间占用更加紧凑。

二、位段

1、什么是位段

1.位段的成员必须是 int、unsigned int 或signed int 。

2.位段的成员名后边有一个冒号和一个数字。

位段后面的冒号代表占用了多少位字节,表示占多少bit位的大小,且设置的大小不能超过原类型最大的大小,例如int 为 4 字节,设置的数字就不能超过 32 。

2、位段的跨平台问题?

1. int 位段被当成有符号数还是无符号数是不确定的。

2. 位段中最大位的数目不能确定。(16位机器最大16,32位机器最大32,写成27,在16位机

器会出问题。

3. 位段中的成员在内存中从左向右分配,还是从右向左分配标准尚未定义。

4. 当一个结构包含两个位段,第二个位段成员比较大,无法容纳于第一个位段剩余的位时,是

舍弃剩余的位还是利用,这是不确定的。

三、枚举

1、枚举的定义

枚举顾名思义就是一个个举例如下方代码

就是从0开始一个个加1,也可以自己定义成员的数值。

enum Day//星期
{
Mon,
Tues,
Wed,
Thur,
Fri,
Sat,
Sun
};
enum Sex//性别
 
{
MALE,
FEMALE,
SECRET
};
enum Color//颜色
{
RED,
GREEN,
BLUE
};

2、枚举的优点与使用

1. 增加代码的可读性和可维护性

2. 和#define定义的标识符比较枚举有类型检查,更加严谨。

3. 防止了命名污染(封装)

4. 便于调试

5. 使用方便,一次可以定义多个常量

使用就如下代码可以直接判断这个数值。

enum Day//星期
{
Mon,
Tues,
Wed,
Thur,
Fri,
Sat,
Sun
};
 
int main()
{
 
    if(Mon==0)
    {
        printf("今天是星期一");
    }
    return 0;
}

四、联合体

联合体也叫做共用体定义方法如下。

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


联合的成员是共用同一块内存空间的,这样一个联合变量的大小,至少是最大成员的大小(因为

联合至少得有能力保存最大的那个成员)。

联合的大小至少是最大成员的大小。

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


目录
相关文章
|
16天前
|
存储 编译器 Linux
C语言——自定义类型
C语言——自定义类型
|
5月前
|
编译器 C语言
C语言进阶⑯(自定义类型)项目:静态通讯录,增删查改排序打印。
C语言进阶⑯(自定义类型)项目:静态通讯录,增删查改排序打印。
48 1
|
19天前
|
存储 编译器 C语言
【C语言】自定义类型:联合与枚举的简明概述
【C语言】自定义类型:联合与枚举的简明概述
|
2月前
|
存储 编译器 C语言
【C语言篇】自定义类型:联合体和枚举详细介绍
像结构体⼀样,联合体也是由⼀个或者多个成员构成,这些成员可以不同的类型。
40 1
|
2月前
|
存储 安全 编译器
C语言自定义类型
C语言自定义类型
31 10
|
4月前
|
编译器 测试技术 C语言
【C语言】:自定义类型:结构体的使用及其内存对齐
【C语言】:自定义类型:结构体的使用及其内存对齐
61 7
TU^
|
4月前
|
编译器 C语言 C++
C语言之自定义类型
C语言之自定义类型
TU^
35 2
|
4月前
|
编译器 C语言 C++
【C语言基础】:自定义类型(二) -->联合和枚举
【C语言基础】:自定义类型(二) -->联合和枚举
|
4月前
|
编译器 C语言
【C语言基础】:自定义类型(一)--> 结构体-2
【C语言基础】:自定义类型(一)--> 结构体
|
4月前
|
编译器 Linux C语言
【C语言基础】:自定义类型(一)--> 结构体-1
【C语言基础】:自定义类型(一)--> 结构体