C语言自定义类型

  在学习 C 语言的早期阶段,我们首先熟悉了基本的数据类型,如 int、double、float 等。然而,随着我们深入学习,逐渐认识到这些基本类型有时无法完整地表达一些复杂概念,比如时间。时间的表示需要涵盖年、月、日、时、分、秒等诸多信息,这显然超出了基本数据类型的限制。因此,为了更准确地描述时间,我们可以利用结构体的特性创建自定义类型,其中包含多个成员变量,用于存储各种时间信息。这一时刻,自定义类型成为我们未来学习道路上不可或缺的利器。

环境

vs2022 x64 debug

枚举

​
enum color {
    RED,    
    GREEN,  
    BLUE    
};

​

        定义一个color类型,枚举类型的语法就是这样,变量之间用" , "  相隔,变量名在enum后

枚举类型大小

我们可以通过定义一个枚举类型,用sizeof计算出他的大小,我们可以看到与int的大小是一样的都是4个字节

特殊

枚举类型特殊的一点是,我们定义在枚举类型的变量是用数字来代替 

联合体

在 C 语言中,联合体(union)是一种特殊的数据类型,它允许在同一内存位置存储不同类型的数据。与结构体不同的是,联合体中的每个成员共享同一块内存空间,因此联合体的大小取决于其最大的成员的大小。这意味着在任何给定的时刻,联合体只能容纳其中一个成员的值。

​
union c
{
	char i;
	int a;
};

​

我们可以使用typedef对联合体类型取别名 

联合体类型大小

我们定义了两个相同的联合体变量,分别对他的两个不同变量赋值,但是最后我们输出的联合体大小是一样的,这就说明,联合体的大小是固定的,跟我们使用联合体的哪个变量没有关系,在第二张图中,联合体变量大小就变成了double类型的大小,二第一张图是int类型的大小,我们可以很容易看出,联合体大小是和联合体变量中最大的那一个有关

特殊

联合体类型的两个变量占用的是同一块空间,我们可以在内存中查看到

结构体

在 C 语言中,结构体(structure)是一种用户定义的数据类型,它可以包含多个不同类型的成员变量。结构体允许我们将多个相关的数据项组合在一起,形成一个逻辑上的整体,从而更方便地管理和操作数据。

​
#include <stdio.h>

// 定义一个结构体表示学生信息
struct Student {
    int id;
    char name[50];
    float gpa;
};

int main() {
    // 声明一个结构体变量
    struct Student s1;

    // 向结构体的成员赋值
    s1.id = 12345;
    strcpy(s1.name, "John");
    s1.gpa = 3.75;

    // 输出结构体的成员值
    printf("Student ID: %d\n", s1.id);
    printf("Student Name: %s\n", s1.name);
    printf("Student GPA: %.2f\n", s1.gpa);

    return 0;
}

​

结构体的主要优点包括

结构体允许将多个相关的数据项组织在一起,形成一个逻辑上的整体,使得数据更易于管理和操作。可以将结构体作为函数的参数,从而方便地传递和操作复杂的数据结构。同时,结构体允许使用有意义的命名来表示数据的不同部分,从而提高了代码的可读性和可维护性。

结构体类型的大小

结构体的大小取决于其成员变量的大小以及对齐方式。在 C 语言中,结构体的大小通常是其成员变量中最大的成员变量的大小的倍数,并且结构体的地址通常是其成员中最大成员的大小的倍数。

具体地说,C 标准并没有规定结构体的内存对齐方式,这由编译器的实现决定。但是大多数编译器会使用某种默认的对齐方式,通常是按照成员变量的大小进行对齐,使得结构体成员的地址是其大小的倍数。

我们可以看到,在结构体中,我们对变量不同的摆放位置不同,结构体的大小就不同,这就说明,编译器处理结构体的数据有其他的规则,而不是简单的把他们的变量大小加在一起分配空间。

这是因为编译器为了节省效率,而这个效率怎么节省的呢。

为了访问未对⻬的内存,处理器需要 作两次内存访问;⽽对⻬的内存访问仅需要⼀次访问。假设⼀个处理器总是从内存中取8个字节,则地 址必须是8的倍数。如果我们能保证将所有的double类型的数据的地址都对⻬成8的倍数,那么就可以 ⽤⼀个内存操作来读或者写值了。否则,我们可能需要执⾏两次内存访问,因为对象可能被分放在两 个8字节内存块中。不同编译器的默认对齐也不一样 vs2022的默认对齐大小是对于 32 位平台,默认对齐大小通常是 4 字节,而对于 64 位平台,默认对齐大小通常是 8 字节。

结构体的使用

​
typedef struct List {
    int* data;
    int A;
    Node* next;
    int B;
} Node, *NodePtr, &NodeRef;

​

我们用typedef对结构体重命名,对List重命名为Node 对List* 重命名为NodePtr 同理 对List& 重命名为NodeRef 也就是 本身,指针与引用,在我们学习C语言链表的时候,可能会看到这样的函数

void ListInit(List* &head)

这就是为了让我们好理解,没有写成二级指针,但是他们可能没有想到,我们还没有学到c++(&)引用,这里我们理解了就好,在C++中,Node* next就可以不用这样写,(C语言这样写更简洁,不用将整个结构体类型全部写出来),但是C++中支持直接用类名!!

对于结构体的学习,他就是一个我们定义的包含不同类型数据的类型,与其他C语言定义的类型使用是一样的,只不过他的类型是

struct List;//或者直接用我们typedef的名字
Node

对于他的指针什么的,用我们重命名的或者就正常使用就可以了

  • 36
    点赞
  • 37
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值