【C语言】结构体、联合体与类型定义

目录

一、类型定义

1.1 struct的定义

1.2 typedef关键字的使用

1.3 typedef的作用和意义

1.3.1 增强可读性

1.3.2 提高可维护性

1.3.3 代码移植性

二、联合

2.1 联合的定义和特点

2.2 联合的内存空间共享

2.2.1 union的用处

节省内存

数据解析

2.3 小端和大端的概念


一、类型定义

1.1 struct的定义

在C语言中,结构体是一种功能强大的自定义数据类型,它允许将不同类型的数据成员组合成一个有机的整体。

结构体的定义以struct关键字开始,紧接着是结构体标签,随后在花括号内罗列结构体的成员列表,最后以分号结束定义。

#include 
//结构体定义
struct Student{
    char name[50];
    int age;
    float score;
};

int main(){
    struct Student stu;
    sprintf(stu.name,"John");
    stu.age = 20;
    stu.score = 90.5;

    printf("name:%s,age:%d,score:%.2f\n",stu.name,stu.age,stu.score);
    return 0;
}

⬇️

  • 定义了一个名为Student的结构体,包含name(用于存储姓名,类型为字符数组)age(存储年龄,类型为整数)以及score(存储分数,类型为浮点数)三个成员。
  • main函数里创建了一个Student类型的变量stu,并通过sprintf函数对name成员进行初始化(这里也可以选择简单的赋值,这里的sprintf只是展示一种方式),同时对age和score成员进行常规赋值,最后将这些信息输出显示。 

结构体成员的访问通过点运算符(  . )来实现,这使得对结构体内部数据的操作直观且边界。

结构体在处理复杂数据结构时表现卓越,例如在描述一个包含多种属性的对象时,结构体能够将这些属性整合在一起,让代码逻辑更加清晰。

1.2 typedef关键字的使用

typedef关键字可以为已有的数据类型创建别名,能够为代码带来更高的可读性和可维护性。

#include 

typedef struct {
    char b[20];
    int year;
} A;

int main() {
    A my;
    sprintf(my.b, "Ben");
    my.year = 2025;

    printf("Word: %s, Year: %d\n", my.b, my.year);
    return 0;
}

⬇️

  • 运用typedef为一个匿名结构体定义了新的类型名A(不建议这样命名,实际上命名要选择自己能记住如拼音、英文单词等,上述只是作演示使用)
  • main函数中声明A类型的变量my时,无需再写struct关键字,这样使代码更加简洁明了。

上述typedef方式在处理复杂数据类型,尤其是嵌套结构体或指针类型时,优势尤为显著,能极大地减少代码的冗余,使代码更易于阅读和维护。

1.3 typedef的作用和意义

1.3.1 增强可读性

一些数据类型的定义可能较为复杂,特别是涉及指针、数组以及结构体的嵌套等情况。

如,指向函数的指针类型声明通常较为冗长,理解起来比较繁琐。

使用typedef为这些复杂类型创建简洁的别名,能够显著提高代码的可读性。

1.3.2 提高可维护性

当项目规模逐渐扩大,代码中可能会多次使用到某些特定的数据类型。如果这些数据类型的定义需要修改,直接在所有使用该类型的地方进行修改将是一项繁琐且容易出错的工作。

而使用typedef,只需要在定义别名的地方进行修改,就能确保整个项目中该类型的一致性。

大大降低了维护成本,提高了代码的可维护性。

1.3.3 代码移植性

在不同的操作系统或硬件平台上,某些数据类型的表示方式或大小可能存在差异。

如,在一些32位系统中,int类型可能占用4个字节,而某些16位系统中可能只占2个字节

通过使用typedef,可以将这些依赖于平台的数据类型进行封装,提高代码的移植性。

二、联合

2.1 联合的定义和特点

联合(union)在C语言中是一种独特的自定义数据类型,它与结构体在形式上有一定相似性,但在数据存储方式上却有着本质的区别。

联合的所有成员共享同一块内存空间,这意味着在同一时刻,联合只能存储其中一个成员的值。

联合的定义以union关键字开头,后跟联合标签(可省略),花括号内是成员列表,最后以分号结束。

#include 

union Data {
    int i;
    float f;
    char str[20];
};
int main(){
    union Data data;
    data.i = 10;
    printf("data.i : %d\n", data.i);

    data.f = 13.5;
    printf("data.f : %.2f\n", data.f);

    sprintf(data.str, "Hello");
    printf("data.str : %s\n", data.str);

    return 0;
}

⬇️

2.2 联合的内存空间共享

联合的内存空间分派是基于最大成员的大小。

由于所有成员共享同一块内存,联合的大小等于其最大成员的大小,这样设计的目的是为了在某些特定场景下节省内存空间。

2.2.1 union的用处

节省内存

在一些对内存资源有限的应用场景中,当需要在不同时刻使用不同类型的数据,但不需要同时存储这些数据时,联合能够有效地节省内存空间。

数据解析

在处理复杂的数据结构时,联合能发挥重要作用。

2.3 小端和大端的概念

在计算机系统中,对于多字节数据类型(如intfloat等)在内存中的存储方式存在小端(Little-Endian)和大端(Big-Endian)两种模式。

  • 小端:数据的低位字节存储在内存的低地址,高位字节存储在内存的高地址。

如,对于一个32位整数0x12345678,在小段模式下,内存中的存储顺序为0x78(最低字节)在低地址,接着是0x56、0x34,最后0x12(最高字节)在高地址。

  • 大端:数据的高位字节存储在内存的低地址,低位字节存储在内存的高地址。

对于上述0x12345678,在大端模式下存储的顺序为0x12(最高字节)在低地址,然后是0x34、0x56,最后0x78(最低字节)在高地址。

#include 

int xiao() {
    union {
        int i;
        char c;
    } u;
    u.i = 1;
    return (u.c == 1);
}

int main() {
    if (xiao()) {
        printf("小端\n");
    } else {
        printf("大端\n");
    }
    return 0;
}

 ⬇️

  •  定义了一个联合u,它包含一个int类型的成员i和一个char类型的成员c
  • i赋值为1,由于int类型在内存中占多个字节,而char类型只占一个字节。
  • 在小端模式下,i的最低字节存储在低地址,当通过c访问联合的内存时,c将获取到i的最低字节,其值为0

正常情况下,个人电脑基本都是小端。

你可能感兴趣的:(#,C语言修仙记(草稿篇),算法,c语言,学习)