c语言基础:结构体、结构体嵌套、结构体指针

50 阅读3分钟

结构体

strusct结构体定义通常放在全局作用域(即函数之外)或局部作用域(函数内部)中。当我们在全局作用域中定义结构体时,这个结构体类型可以在定义之后的任何地方使用,包括各个函数内部。但是,结构体定义并不分配内存,它只是定义了一种数据类型。

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

// 定义同时声明变量
struct Point {
    int x;
    int y;
} p1, p2;

// 使用typedef简化
typedef struct {
    char title[50];
    char author[30];
    float price;
} Book;

typedef

**typedef**是C语言中的一个关键字,用于为已有的数据类型创建新的类型别名。

typedef struct {
  int id;
  int age;
  char *name;
  float score;
} Student1;

typedef struct Student1 Student;//为 struct Student1 结构体类型创建一个新的别名 Student。

int main() {
  Student stu1;
  return 0;
}

结构体嵌套

typedef struct  {
  int year;//年
  int month;//月
  int day;//日
}Birthday;

typedef struct  {
  int id;//学号
  int age;//年龄
  char *name;//姓名
  float score;//成绩
  Birthday birthday;
}Student1;

int main() {
  Student1 stu1,stu2,stu3;//可以定义多个变量名
  stu1.birthday.day = 1;//使用点进行多层访问
  return 0;
}

结构体赋值及打印

a27ffa04-47e3-4995-8152-e88737586047.png

结构体指针

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

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

int main() {
    // 1. 声明结构体变量和指针
    Student stu1 = {1, "张三", 20, 85.5};
    Student *pStu;  // 声明结构体指针
    
    // 2. 让指针指向结构体变量
    pStu = &stu1;
    
    // 3. 通过指针访问结构体成员(使用箭头运算符 ->)
    printf("通过指针访问:\n");
    printf("学号: %d\n", pStu->id);
    printf("姓名: %s\n", pStu->name);
    printf("年龄: %d\n", pStu->age);
    printf("成绩: %.1f\n", pStu->score);
    
    // 4. 通过指针修改结构体成员
    pStu->age = 21;
    pStu->score = 90.0;
    strcpy(pStu->name, "张三丰");
    
    printf("\n修改后:\n");
    printf("学号: %d\n", pStu->id);
    printf("姓名: %s\n", pStu->name);
    printf("年龄: %d\n", pStu->age);
    printf("成绩: %.1f\n", pStu->score);
    
    return 0;
}

嵌套结构体指针

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

typedef struct {
    int year;
    int month;
    int day;
} Birthday;

typedef struct {
    int id;
    char name[20];
    Birthday birthday;  // 嵌套结构体
    float score;
} Student;

// 创建学生
Student* createStudent(int id, const char *name, int year, int month, int day, float score) {
    Student *pStu = (Student*)malloc(sizeof(Student));
    if (pStu != NULL) {
        pStu->id = id;
        strcpy(pStu->name, name);
        pStu->birthday.year = year;
        pStu->birthday.month = month;
        pStu->birthday.day = day;
        pStu->score = score;
    }
    return pStu;
}

// 打印学生信息
void printStudent(const Student *pStu) {
    if (pStu == NULL) return;
    
    printf("学生信息:\n");
    printf("  学号: %d\n", pStu->id);
    printf("  姓名: %s\n", pStu->name);
    printf("  生日: %d年%d月%d日\n", 
           pStu->birthday.year, 
           pStu->birthday.month, 
           pStu->birthday.day);
    printf("  成绩: %.1f\n", pStu->score);
}

// 通过指针修改生日
void updateBirthday(Student *pStu, int year, int month, int day) {
    if (pStu != NULL) {
        pStu->birthday.year = year;
        pStu->birthday.month = month;
        pStu->birthday.day = day;
    }
}

int main() {
    // 创建学生指针
    Student *pStu = createStudent(1, "小明", 2000, 5, 15, 85.5);
    
    if (pStu != NULL) {
        printStudent(pStu);
        
        // 修改生日
        updateBirthday(pStu, 2001, 6, 20);
        printf("\n修改生日后:\n");
        printStudent(pStu);
        
        // 直接通过指针访问嵌套结构体
        printf("\n直接访问嵌套结构体:\n");
        printf("年份: %d\n", pStu->birthday.year);
        printf("月份: %d\n", pStu->birthday.month);
        printf("日期: %d\n", pStu->birthday.day);
        
        free(pStu);
    }
    
    return 0;
}

结构体指针的重要知识点

  1. 箭头运算符p->member 等价于 (*p).member
  2. 内存管理:动态分配的结构体指针必须手动释放
  3. 函数参数:传递指针比传递整个结构体更高效
  4. 深拷贝与浅拷贝:包含指针的结构体需要深拷贝
  5. const保护:使用const Student *p防止意外修改