结构体(初阶)

🏗️ 一、结构体 vs 数组:数据组织的升级 🧺

核心区别

数据类型特点示例场景
数组相同类型数据的集合存储 5 个学生的年龄(int 数组)
结构体不同类型数据的集合存储 1 个学生的完整信息(姓名 + 年龄 + 成绩)

一句话总结

结构体是用 struct 关键字定义的 “复合数据类型”,可以把不同类型的数据(如 intcharfloat)打包成一个整体。

二、结构体定义:语法格式与位置 📑

1. 定义格式(主函数外定义)

// 结构体标签:Student(相当于自定义类型名)
struct Student { 
    char name[20];   // 成员变量1:字符数组(姓名)
    int age;        // 成员变量2:整数(年龄)
    float score;    // 成员变量3:浮点数(成绩)
};  // 分号不能少!
部分说明
struct关键字,声明这是一个结构体定义
Student结构体标签(类型名),后续声明变量需用 struct Student 或 typedef 简化
{ }包裹成员列表,每个成员以分号结尾
末尾分号 ;结构体定义的结束标志,漏写会导致编译错误

2. 定义时直接声明变量(全局 / 局部)

// 全局结构体变量(在主函数外声明)
struct Student { 
    char name[20];   // 成员变量1:字符数组(姓名)
    int age;        // 成员变量2:整数(年龄)
    float score;    // 成员变量3:浮点数(成绩)
}stu1;     // stu1 是结构体变量,也是全局变量。

//或者在定义结构体之后,写:struct Student stu1; 

int main() {
    // 局部结构体变量(在主函数内声明)
    struct Student stu2;  
    return 0;
}

🚨 注意事项

  • 结构体标签:定义时必须写 struct Student 
  • 分号必填:结构体定义末尾的分号容易漏写,会导致编译错误。

三、结构体初始化📦

1. 按顺序初始化(最常用)

struct Student {
    char name[20];
    int age;
    float score;
};

// 定义全局变量时直接初始化(按成员顺序赋值)
struct Student stu = {
    "小明",      // 对应 char name[20](字符数组初始化)
    18,         // 对应 int age
    85.5        // 对应 float score
};  
🔍 初始化规则
  • 花括号内的值按结构体成员定义的顺序依次赋值。
  • 字符数组:用双引号字符串直接初始化(如 "小明"),长度不超过数组声明的大小(20)。
  • 基本类型:直接写对应类型的值(整数、浮点数)。

2. 指定成员初始化

struct Student stu = {
    .age = 20,       // 显式指定初始化age成员
    .name = "小红",  // 初始化name成员
    .score = 90.0    // 初始化score成员(顺序可乱)
};
  • 无需严格按成员顺序,可读性更强,避免因成员顺序变化导致的错误。
  • 未指定的成员自动初始化为 0(数值型)或空字符(字符型)。

3. 嵌套结构体初始化(成员是另一个结构体)

// 先定义地址结构体
struct Address {
    char city[20];
    char street[30];
};

// 学生结构体包含地址结构体成员
struct Student {
    char name[20];
    int age;
    struct Address addr;  // 成员是另一个结构体
};

// 初始化嵌套结构体
struct Student stu = {
    "小刚",
    19,
    {   // 嵌套结构体的初始化括号
        "北京市",
        "长安街10号"
    }
};

🚨 易错

  • 多层括号:嵌套结构体初始化时,内层结构体要用额外的 {} 包裹,否则编译报错。
  • 类型匹配:初始化值的类型必须与成员类型一致(如 name 是数组,需要用字符串常量初始化)。

四、结构体变量的使用🔑

1. 通过变量名访问(‘ . ' 操作符)

#include <stdio.h>

// 定义结构体类型
struct Student {
    char name[20];
    int age;
    float score;
};

// 全局结构体变量(定义在所有函数之外)
struct Student stu = { "小明", 18, 85.5 };

int main() {
    // 通过全局变量名 `stu` 访问成员(. 操作符)
    printf("全局变量访问:\n");
    printf("姓名: %s\n", stu.name);   // 输出:小明
    printf("年龄: %d\n", stu.age);    // 输出:18
    printf("成绩: %.1f\n", stu.score); // 输出:85.5

    // 修改全局变量的成员
    stu.age = 19;
    printf("\n修改后年龄: %d\n", stu.age); // 输出:19
    return 0;
}
关键点:
  • 作用域stu 是全局变量,在整个文件内可见(包括 main 函数)。
  • 访问格式:直接通过 变量名.成员名 操作,无需额外声明。
  • 内存位置:全局变量存储在数据段,生命周期贯穿程序始终。

2. 通过指针访问(-> 操作符)

struct Student* p = &stu;  // 定义结构体指针,指向stu

printf("姓名:%s\n", p->name);  // 用 -> 访问成员(等价于 (*p).name)
printf("年龄:%d\n", p->age);

🚨 注意事项

  • 操作符区别
    • 结构体变量用 .:如 stu.name
    • 结构体指针用 ->:如 p->name(不能写成 p.name

五、结构体定义的 2种写法📝

1. 标准写法(最清晰)

// 定义结构体标签
struct Student { 
    char name[20];
    int age;
};

// 声明变量
struct Student stu;

2. 用 typedef 简化写法(推荐)


//  用 typedef 定义结构体别名(替代 struct Student)
typedef struct {
    char name[20];
    int age;
    float score;
} Student;  // 别名:Student 等价于 struct { ... }

六、结构体成员是另一个结构体:嵌套案例 🏘️

🌰 案例:学生结构体包含地址结构体

// 定义地址结构体(成员是字符串)
typedef struct {
    char city[20];
    char street[30];
} Address;

// 定义学生结构体,包含地址结构体成员
typedef struct {
    char name[20];
    int age;
    Address home;  // 成员是Address结构体
} Student;

int main() {
    // 初始化嵌套结构体
    Student stu = {
        "小孙",
        20,
        {   // 初始化Address成员
            "徐州市",
            "欣欣路"
        }
    };

    // 访问嵌套成员
    printf("家庭地址:%s %s\n", stu.home.city, stu.home.street);
    return 0;
}

🚨 关键点

  • 嵌套成员的访问:通过多层 . 操作符,如 stu.home.city
  • 初始化顺序:先外层结构体成员,再内层结构体的 {} 包裹初始化值。

七、必看!结构体五大易错点 🚫

  1. 漏写 struct 关键字
    ❌ 错误:Student stu;(需先 typedef 或写 struct Student
    ✅ 正确:struct Student stu; 或 typedef struct Student Student;

  2. 结构体定义末尾漏分号
    ❌ 错误:struct Student { ... }(末尾无分号)
    ✅ 正确:struct Student { ... };(分号必填)

  3. 指针访问成员用错操作符
    ❌ 错误:p.name(指针需用 ->
    ✅ 正确:p->name 或 (*p).name

  4. 嵌套初始化少括号
    ❌ 错误:{ "小明", 18, "北京市", "长安街" }(缺少内层{}
    ✅ 正确:{ "小明", 18, { "北京市", "长安街" } }

  5. 给数组成员直接赋值
    ❌ 错误:stu.name = "小红";(数组不能直接赋值)
    ✅ 正确:strcpy(stu.name, "小红");(需包含头文件 <string.h>

  6. 结构体成员(如:name/age/score

    • 它们是结构体类型的字段,既不是全局变量也不是局部变量
    • 属于结构体Student的定义部分,作用域仅限于结构体实例
    • 必须通过结构体变量(如stu)访问,例如:stu.namestu.age

🌟 总结:结构体知识点

概念说明
定义格式struct 标签 { 成员列表; };,末尾分号必填
初始化按顺序或指定成员初始化,嵌套结构体用多层{}
访问成员变量用 ‘ . ',指针用 ->
嵌套成员成员可以是另一个结构体,初始化时内层用{}包裹
typedef简化写法,避免重复写struct,如typedef struct Student Student;

💡 建议

  1. 多用 typedef:定义结构体时用 typedef,避免每次写 struct
  2. 初始化顺序对应:按成员顺序写初始化值,或显式指定成员(如 .age = 20),可读性更强。

结构体是 C 语言组织复杂数据的核心,掌握后能让代码更有条理。

 动手写几个案例,很快就能上手! 🚀

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值