C语言——> 结构体

本文详细介绍了C语言中结构体的基本概念,包括结构体的定义、结构体变量的定义及引用方式,同时还探讨了结构体数组、指向结构体的指针以及如何在函数间传递结构体等内容。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

结构体

结构体和共用体就是C语言提供的用于处理复杂数据类型的方式允许用户自定义数据类型在C语言中为构造数据类型(也称复合数据类型

它允许用户根据自己的需要利用已有的基本数据类型在制造出自己所需的数据类型。用于表示链表,树,堆栈等复杂的数据对象。

结构体的定义

数组:是由同类型的数据构成的一种数据结构,适合于对具有相同属性的数据进行批处理

结构体:是将不同类型的数据成员组织到统一的名字之下,适合于对关系密切、逻辑相关、具有相同或者不同属性的数据进行处理

共用体:虽然也能表示逻辑相关的不同类型的数据集合,但其数据成员是情形互斥的,每一刻只有一个数据成员起作用

结构体变量的定义

结构体模板的标准格式:

struct 结构体名
{
    数据类型 成员1的名字;
    数据类型 成员2的名字;
    数据类型 成员3的名字;
    ……
    数据类型 成员n的名字;
    
}/*注意,这里的分号不能忘了写*/

结构体标签:结构体的名字,作为用户自定义的结构体类型的标志,用于与其他结构体类型相区别。

结构体的各种信息是在{}中声明的

结构体成员:构成结构体的变量,每个结构体成员都有一个名字和相应的数据类型,其命名必须遵循变量的命名规则

注意,结构体模板只是声明了一种数据类型,定义了数据的组织形式,并未声明结构体类型的变量


C语言允许一下两种方法定义结构体变量:

第一种:先声明结构体模板,再定义结构体变量

struct 结构体名
{
    数据类型 成员1的名字;
    数据类型 成员2的名字;
    数据类型 成员3的名字;
    ……
    数据类型 成员n的名字;
    
};
 struct student stu1;

第二种:在声明结构体模板的同时定义结构体变量

struct 结构体名
{
    数据类型 成员1的名字;
    数据类型 成员2的名字;
    数据类型 成员3的名字;
    ……
    数据类型 成员n的名字;
    
}stu1;

用typedef(关键字)定义数据类型

关键字typedef用于为系统固有的或程序员自定义的数据类型定义一个别名。

通常数据类型的别名都是全英文大写的

typedef int INTEGER; /*将int重新命名为INTEGER*/
typedef struct student STUDENT;/*将自己制造的student类型重命名为STUDENT*/
or
typedef struct student
{
    数据类型 成员1的名字;
    数据类型 成员2的名字;
    数据类型 成员3的名字;
    ……
    数据类型 成员n的名字;
    
}STUDENT;
    

上述的定义STUDENT的两个代码是等价的;

typedef只是为一种已存在的类型定义一个名字而已,并未定义一种新的数据类型

嵌套的结构体

嵌套的结构体就是在一个结构体内包含了另一个结构体作为其成员

typedef struct date
{
    int year;
    int month;
    int day;
}DATE;
typedef struct student
{
    char name[];
    int ID;
    DATE birthday;
}STUDENT

结构体变量的引用


C语言规定,不能将一个结构体变量作为一个整体进行输入,输出操作,只能对每个具体的成员进行输入,输出操作


访问格式: 结构体变量名 . 成员名

当引用嵌套体时,必须一级一级地通过访问格式找到最底层的成员后再引用

eg:stu1.birthday.day


C语言允许对具有相同结构体类型的变量进行整体赋值。

stu1 = stu2;

这样是非法的;

并非所有的结构体成员都可以使用赋值运算符来赋值,对字符数组类型成员进行赋值时,必须使用字符串处理函数strcpy()

结构体变量也和基本的变量一样有作用域,在函数外定义的结构体变量是全局声明,在函数内部定义的结构体变量是局部声明

结构体变量的地址是结构体变量所占内存空间的首地址,而结构体成员的地址值与结构体成员在结构体中所处的位置及其该成员所占内存的字节数有关

结构体所占内存的字节数

有四字节对齐原则

结构体数组的定义和初始化

结构体数组的定义

与基本的数据类型相同,结构体也是有其对应的数组的,是代表有与结构体中每个元素相同的一系类结构体的集合

结构体数组的初始化

可以在定义结构体数组时就对其进行初始化,和字符数组一样

也可以通过scanf()函数进行初始化,不过要注意每个结构体元素对应的数据类型

指向结构体的指针

结构一也是有指针的,定义结构体指针的方法如下:

第一种:STUDENT *pt = stu;

第二种:STUDENT *pt = &stu[0];

第三种:STUDENT *pt;

​ pt = stu;

以上三种定义的方法都是等价的

向函数传递结构体

第一种:用结构体的单个成员作为函数参数,向函数传递结构体的单个成员

第二种:用结构体变量作为函数参数,向函数传递结构体的完整结构

第三种:通过结构体指针或结构体数组作为函数参数,向函数传递结构体的地址


### C语言结构体嵌套结构体的用法和示例 #### 结构体嵌套的概念 在C语言中,结构体可以作为另一个结构体的成员。这种特性被称为**结构体嵌套**。通过这种方式,程序员能够创建更复杂的自定义数据类型来表示现世界中的对象及其属性。 #### 示例代码 下面是一个简单的例子展示如何在一个结构体内嵌入另一个结构体: ```c #include <stdio.h> // 定义一个描述日期的结构体 struct Date { int day; int month; int year; }; // 定义一个员工信息的结构体,其中包含了一个Date类型的成员 struct Employee { int id; char name[50]; struct Date join_date; // 嵌套结构体 }; int main() { // 创建Employee结构体的一个例并初始化其字段 struct Employee emp = {1, "Alice", {1, 1, 2023}}; printf("Employee ID: %d\n", emp.id); printf("Employee Name: %s\n", emp.name); printf("Joining Date: %d/%d/%d\n", emp.join_date.day, emp.join_date.month, emp.join_date.year); return 0; } ``` 在这个程序里,`struct Date` 被用来保存日期的相关信息,而 `struct Employee` 则包含了关于员工的信息以及他们的入职日期。这表明了即使是在相对简单的场景下,嵌套结构体也可以让代码更加清晰易读[^2]。 #### 动态内存管理与灵活性 如果需要动态地操作这些复合的数据结构,则可以通过指针来进行进一步的操作。例如,在某些情况下可能不知道提前有多少名雇员要录入系统,这时就可以利用malloc函数为每一个新的记录申请空间: ```c struct Employee* new_emp = (struct Employee*) malloc(sizeof(struct Employee)); if(new_emp != NULL){ (*new_emp).id = 2; strcpy((*new_emp).name,"Bob"); (*new_emp).join_date.day=2; (*new_emp).join_date.month=2; (*new_emp).join_date.year=2024; free(new_emp); // 记得释放不再使用的资源 }else{ perror("Failed to allocate memory."); } ``` 这里展示了如何使用指向结构体的指针,并且还强调了良好的编程习惯——总是检查分配请求的结果是否成功,最后记得清理已不需要的动态分配区域以防泄露[^1]。 #### 总结 结构体嵌套提供了构建层次化、模块化的数据模型的能力,使得程序设计者可以根据际需求组合不同类型的数据单元形成整体解决方案的一部分。无论是静态还是动态环境下都能找到合适的应用场合。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值