C语言结构体详解:从入门到精通

C语言结构体详解:从入门到精通

1. 结构体基本概念

什么是结构体?

结构体是C语言中用户自定义的数据类型,允许将不同类型的数据组合成一个单一类型。

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

// 定义结构体类型
struct Student {
    char name[50];
    int age;
    float grade;
    char id[10];
};

int main() {
    // 声明结构体变量
    struct Student student1;
    
    // 初始化结构体成员
    strcpy(student1.name, "张三");
    student1.age = 20;
    student1.grade = 85.5;
    strcpy(student1.id, "2024001");
    
    // 访问结构体成员
    printf("学生信息:\n");
    printf("姓名: %s\n", student1.name);
    printf("年龄: %d\n", student1.age);
    printf("成绩: %.1f\n", student1.grade);
    printf("学号: %s\n", student1.id);
    
    return 0;
}

输出:

学生信息:
姓名: 张三
年龄: 20
成绩: 85.5
学号: 2024001

2. 结构体声明和初始化

2.1 多种声明方式

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

// 方式1:先定义类型,再声明变量
struct Point {
    int x;
    int y;
};

// 方式2:定义类型的同时声明变量
struct Rectangle {
    int width;
    int height;
} rect1, rect2;

// 方式3:使用typedef创建别名
typedef struct {
    char title[100];
    char author[50];
    float price;
} Book;

int main() {
    // 初始化结构体
    struct Point p1 = {10, 20};  // 顺序初始化
    struct Point p2 = {.y = 30, .x = 15};  // 指定成员初始化
    
    // 声明后赋值
    rect1.width = 100;
    rect1.height = 50;
    
    // 使用typedef别名
    Book book1 = {"C语言教程", "李教授", 45.5};
    
    printf("点p1: (%d, %d)\n", p1.x, p1.y);
    printf("点p2: (%d, %d)\n", p2.x, p2.y);
    printf("矩形: %dx%d\n", rect1.width, rect1.height);
    printf("书籍: 《%s》作者:%s 价格:%.1f元\n", 
           book1.title, book1.author, book1.price);
    
    return 0;
}

输出:

点p1: (10, 20)
点p2: (15, 30)
矩形: 100x50
书籍: 《C语言教程》作者:李教授 价格:45.5元

3. 结构体数组

3.1 结构体数组的使用

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

typedef struct {
    char name[30];
    int employee_id;
    float salary;
    char department[20];
} Employee;

int main() {
    // 声明并初始化结构体数组
    Employee employees[3] = {
        {"张三", 1001, 8000.0, "技术部"},
        {"李四", 1002, 7500.0, "市场部"},
        {"王五", 1003, 9000.0, "技术部"}
    };
    
    printf("员工信息表:\n");
    printf("%-10s %-8s %-10s %-12s\n", "姓名", "工号", "工资", "部门");
    printf("----------------------------------------\n");
    
    // 遍历结构体数组
    for(int i = 0; i < 3; i++) {
        printf("%-10s %-8d %-10.2f %-12s\n", 
               employees[i].name, 
               employees[i].employee_id,
               employees[i].salary,
               employees[i].department);
    }
    
    // 计算平均工资
    float total_salary = 0;
    for(int i = 0; i < 3; i++) {
        total_salary += employees[i].salary;
    }
    printf("\n平均工资: %.2f元\n", total_salary / 3);
    
    return 0;
}

输出:

员工信息表:
姓名       工号     工资       部门        
----------------------------------------
张三       1001     8000.00    技术部       
李四       1002     7500.00    市场部       
王五       1003     9000.00    技术部       

平均工资: 8166.67元

4. 结构体指针

4.1 结构体指针的使用

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

typedef struct {
    char model[50];
    int year;
    float price;
} Car;

int main() {
    // 栈上结构体
    Car car1 = {"Toyota Camry", 2023, 215000.0};
    Car *car_ptr = &car1;  // 指向结构体的指针
    
    // 通过指针访问成员(两种方式)
    printf("汽车信息:\n");
    printf("型号: %s\n", (*car_ptr).model);  // 方式1
    printf("年份: %d\n", car_ptr->year);     // 方式2(推荐)
    printf("价格: %.2f\n", car_ptr->price);
    
    // 动态分配结构体
    Car *dynamic_car = (Car*)malloc(sizeof(Car));
    if(dynamic_car != NULL) {
        strcpy(dynamic_car->model, "Honda Accord");
        dynamic_car->year = 2024;
        dynamic_car->price = 198000.0;
        
        printf("\n动态分配汽车:\n");
        printf("型号: %s\n", dynamic_car->model);
        printf("年份: %d\n", dynamic_car->year);
        printf("价格: %.2f\n", dynamic_car->price);
        
        free(dynamic_car);  // 释放内存
    }
    
    return 0;
}

输出:

汽车信息:
型号: Toyota Camry
年份: 2023
价格: 215000.00

动态分配汽车:
型号: Honda Accord
年份: 2024
价格: 198000.00

5. 结构体与函数

5.1 结构体作为函数参数

#include <stdio.h>
#include <math.h>

typedef struct {
    double real;
    double imag;
} Complex;

// 结构体作为值传递
void printComplex(Complex c) {
    printf("%.2f + %.2fi\n", c.real, c.imag);
}

// 结构体作为指针传递(避免复制开销)
Complex addComplex(Complex *a, Complex *b) {
    Complex result;
    result.real = a->real + b->real;
    result.imag = a->imag + b->imag;
    return result;
}

// 计算复数模长
double complexMagnitude(Complex *c) {
    return sqrt(c->real * c->real + c->imag * c->imag);
}

int main() {
    Complex num1 = {3.0, 4.0};
    Complex num2 = {1.5, 2.5};
    
    printf("复数1: ");
    printComplex(num1);
    
    printf("复数2: ");
    printComplex(num2);
    
    Complex sum = addComplex(&num1, &num2);
    printf("相加结果: ");
    printComplex(sum);
    
    printf("复数1的模长: %.2f\n", complexMagnitude(&num1));
    
    return 0;
}

输出:

复数1: 3.00 + 4.00i
复数2: 1.50 + 2.50i
相加结果: 4.50 + 6.50i
复数1的模长: 5.00

6. 结构体嵌套

6.1 嵌套结构体

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

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

typedef struct {
    char name[50];
    Date birth_date;
    struct {  // 匿名结构体
        char street[100];
        char city[50];
        char zip_code[10];
    } address;
} Person;

int main() {
    Person person1;
    
    strcpy(person1.name, "王小明");
    person1.birth_date.day = 15;
    person1.birth_date.month = 8;
    person1.birth_date.year = 1995;
    strcpy(person1.address.street, "人民路123号");
    strcpy(person1.address.city, "北京市");
    strcpy(person1.address.zip_code, "100000");
    
    printf("个人信息:\n");
    printf("姓名: %s\n", person1.name);
    printf("出生日期: %d年%d月%d日\n", 
           person1.birth_date.year,
           person1.birth_date.month, 
           person1.birth_date.day);
    printf("地址: %s%s (%s)\n", 
           person1.address.city,
           person1.address.street,
           person1.address.zip_code);
    
    return 0;
}

输出:

个人信息:
姓名: 王小明
出生日期: 1995年8月15日
地址: 北京市人民路123号 (100000)

7. 结构体大小与内存对齐

7.1 结构体大小计算

#include <stdio.h>

struct Example1 {
    char a;     // 1字节
    int b;      // 4字节
    char c;     // 1字节
}; // 可能为12字节(对齐)

struct Example2 {
    int b;      // 4字节
    char a;     // 1字节
    char c;     // 1字节
}; // 可能为8字节(更紧凑)

#pragma pack(1)  // 取消对齐
struct Example3 {
    char a;
    int b;
    char c;
}; // 6字节(无对齐)
#pragma pack()   // 恢复默认对齐

int main() {
    printf("结构体大小:\n");
    printf("Example1: %zu 字节\n", sizeof(struct Example1));
    printf("Example2: %zu 字节\n", sizeof(struct Example2));
    printf("Example3: %zu 字节\n", sizeof(struct Example3));
    
    // 查看成员偏移量
    struct Example1 ex1;
    printf("\n成员偏移量:\n");
    printf("a: %p\n", (void*)&ex1.a);
    printf("b: %p\n", (void*)&ex1.b);
    printf("c: %p\n", (void*)&ex1.c);
    
    return 0;
}

输出:

结构体大小:
Example1: 12 字节
Example2: 8 字节
Example3: 6 字节

成员偏移量:
a: 0x7ffd3a4a4a30
b: 0x7ffd3a4a4a34
c: 0x7ffd3a4a4a38

8. 结构体高级特性

8.1 结构体位域

#include <stdio.h>

// 位域结构体
typedef struct {
    unsigned int is_active : 1;    // 1位
    unsigned int priority  : 3;    // 3位 (0-7)
    unsigned int type      : 4;    // 4位 (0-15)
    unsigned int reserved  : 24;   // 24位保留
} PacketHeader;

typedef struct {
    unsigned char red   : 5;   // 5位 (0-31)
    unsigned char green : 6;   // 6位 (0-63)
    unsigned char blue  : 5;   // 5位 (0-31)
} RGB15;

int main() {
    PacketHeader header;
    header.is_active = 1;
    header.priority = 5;
    header.type = 12;
    
    printf("数据包头部:\n");
    printf("是否激活: %u\n", header.is_active);
    printf("优先级: %u\n", header.priority);
    printf("类型: %u\n", header.type);
    printf("总大小: %zu 字节\n", sizeof(header));
    
    RGB15 color;
    color.red = 31;    // 最大值
    color.green = 63;  // 最大值
    color.blue = 31;   // 最大值
    
    printf("\nRGB颜色:\n");
    printf("红色: %u\n", color.red);
    printf("绿色: %u\n", color.green);
    printf("蓝色: %u\n", color.blue);
    printf("总大小: %zu 字节\n", sizeof(color));
    
    return 0;
}

输出:

数据包头部:
是否激活: 1
优先级: 5
类型: 12
总大小: 4 字节

RGB颜色:
红色: 31
绿色: 63
蓝色: 31
总大小: 2 字节

9. 结构体实际应用

9.1 学生管理系统

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

#define MAX_STUDENTS 100

typedef struct {
    char name[50];
    int id;
    float scores[3];  // 三门课程成绩
    float average;
} Student;

void inputStudent(Student *s) {
    printf("请输入姓名: ");
    scanf("%s", s->name);
    printf("请输入学号: ");
    scanf("%d", &s->id);
    printf("请输入三门课程成绩: ");
    scanf("%f %f %f", &s->scores[0], &s->scores[1], &s->scores[2]);
    
    // 计算平均分
    s->average = (s->scores[0] + s->scores[1] + s->scores[2]) / 3.0;
}

void printStudent(const Student *s) {
    printf("%-10s %-8d %-6.1f %-6.1f %-6.1f %-6.1f\n", 
           s->name, s->id, 
           s->scores[0], s->scores[1], s->scores[2],
           s->average);
}

void findTopStudent(Student students[], int count) {
    int top_index = 0;
    for(int i = 1; i < count; i++) {
        if(students[i].average > students[top_index].average) {
            top_index = i;
        }
    }
    
    printf("\n最高分学生:\n");
    printStudent(&students[top_index]);
}

int main() {
    Student students[MAX_STUDENTS];
    int count;
    
    printf("请输入学生数量: ");
    scanf("%d", &count);
    
    if(count > MAX_STUDENTS) {
        printf("数量超过最大值!\n");
        return 1;
    }
    
    // 输入学生信息
    for(int i = 0; i < count; i++) {
        printf("\n学生 %d:\n", i + 1);
        inputStudent(&students[i]);
    }
    
    // 显示所有学生
    printf("\n%-10s %-8s %-6s %-6s %-6s %-6s\n", 
           "姓名", "学号", "成绩1", "成绩2", "成绩3", "平均分");
    printf("------------------------------------------------\n");
    for(int i = 0; i < count; i++) {
        printStudent(&students[i]);
    }
    
    // 查找最高分学生
    findTopStudent(students, count);
    
    return 0;
}

输出示例:

请输入学生数量: 2

学生 1:
请输入姓名: 张三
请输入学号: 1001
请输入三门课程成绩: 85 90 78

学生 2:
请输入姓名: 李四
请输入学号: 1002
请输入三门课程成绩: 92 88 95

姓名       学号     成绩1  成绩2  成绩3  平均分  
------------------------------------------------
张三       1001     85.0   90.0   78.0   84.3  
李四       1002     92.0   88.0   95.0   91.7  

最高分学生:
李四       1002     92.0   88.0   95.0   91.7  

10. 结构体与联合体

10.1 结构体中的联合体

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

typedef union {
    int int_value;
    float float_value;
    char string_value[20];
} Data;

typedef struct {
    int data_type;  // 1-int, 2-float, 3-string
    Data data;
} Variant;

void printVariant(Variant *v) {
    printf("数据类型 %d: ", v->data_type);
    switch(v->data_type) {
        case 1:
            printf("整数 %d\n", v->data.int_value);
            break;
        case 2:
            printf("浮点数 %.2f\n", v->data.float_value);
            break;
        case 3:
            printf("字符串 %s\n", v->data.string_value);
            break;
        default:
            printf("未知类型\n");
    }
}

int main() {
    Variant vars[3];
    
    vars[0].data_type = 1;
    vars[0].data.int_value = 100;
    
    vars[1].data_type = 2;
    vars[1].data.float_value = 3.14159;
    
    vars[2].data_type = 3;
    strcpy(vars[2].data.string_value, "Hello World");
    
    printf("变体类型示例:\n");
    for(int i = 0; i < 3; i++) {
        printVariant(&vars[i]);
    }
    
    printf("\n联合体大小: %zu 字节\n", sizeof(Data));
    printf("变体结构体大小: %zu 字节\n", sizeof(Variant));
    
    return 0;
}

输出:

变体类型示例:
数据类型 1: 整数 100
数据类型 2: 浮点数 3.14
数据类型 3: 字符串 Hello World

联合体大小: 20 字节
变体结构体大小: 24 字节

总结

关键知识点:

  1. 结构体定义:使用struct关键字,可配合typedef
  2. 成员访问:使用点运算符(.)或箭头运算符(->)
  3. 内存布局:注意内存对齐对大小的影响
  4. 嵌套结构:结构体中可以包含其他结构体
  5. 位域:节省内存的特殊用法
  6. 函数参数:可传递结构体值或指针

最佳实践:

  1. 使用typedef创建有意义的类型名
  2. 传递大结构体时使用指针避免复制开销
  3. 注意结构体内存对齐,合理安排成员顺序
  4. 使用位域节省内存,但要注意可移植性
  5. 结构体初始化时使用指定成员初始化提高可读性

结构体是C语言中组织复杂数据的核心工具,掌握好结构体对编写高质量的C程序至关重要!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值