C语言结构体

一、结构体(Structures)的基本概念

结构体是一种用户自定义的数据类型,它能够把不同类型的数据组合在一起。

1. 结构体的定义与初始化
// 定义结构体
struct Person {
    char name[50];
    int age;
    float height;
};

// 初始化结构体变量
struct Person p1 = {"Alice", 25, 1.65};
struct Person p2;
p2.age = 30; // 成员访问
2. 结构体指针
struct Point {
    int x;
    int y;
};

struct Point pt = {10, 20};
struct Point *ptr = &pt;
ptr->x = 15; // 等价于(*ptr).x
3. 结构体数组
struct Student {
    char name[20];
    int score;
};

struct Student class[3] = {
    {"Bob", 85},
    {"Tom", 92},
    {"Lily", 78}
};
4. 结构体嵌套
struct Date {
    int year;
    int month;
    int day;
};

struct Employee {
    char name[30];
    struct Date hire_date;
};
5. 结构体作为函数参数
void printPerson(struct Person p) {
    printf("%s, %d years old\n", p.name, p.age);
}

// 传递结构体指针(高效)
void updateAge(struct Person *p, int new_age) {
    p->age = new_age;
}
6. 位域(Bit Fields)
struct Flags {
    unsigned int is_admin : 1; // 1位
    unsigned int is_logged : 1;
    unsigned int permission : 2; // 2位(0-3)
};

二、结构体变量的引用方式

1. 点运算符(.

用于通过结构体变量直接访问成员:

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

struct Student s1 = {"Alice", 20};
printf("Name: %s\n", s1.name);  // 直接访问
s1.age = 21;                    // 直接修改
2. 箭头运算符(->

用于通过结构体指针间接访问成员:

struct Point { int x, y; };
struct Point p = {10, 20};
struct Point *ptr = &p;

ptr->x = 15;        // 等价于 (*ptr).x = 15;
printf("Y: %d\n", ptr->y);  // 输出20
3. 嵌套结构体的访问
struct Date { int year, month, day; };
struct Employee {
    char name[30];
    struct Date hire_date;
};

struct Employee e = {"Bob", {2022, 5, 15}};
printf("Hire Year: %d\n", e.hire_date.year);  // 多级访问

三、结构体数组的引用

struct Rectangle {
    int width;
    int height;
};

struct Rectangle rects[2] = { {10, 20}, {30, 40} };

// 访问第二个矩形的面积
int area = rects[1].width * rects[1].height;

四、结构体作为函数参数的引用

1. 传递结构体值(副本)
void printStudent(struct Student s) {
    printf("Name: %s, Age: %d\n", s.name, s.age);
}

// 调用
printStudent(s1);  // 传递副本
2. 传递结构体指针(高效)
void updateStudent(struct Student *s) {
    s->age++;  // 修改原始数据
}

// 调用
updateStudent(&s1);  // 传递地址

五、自引用结构体的引用

struct Node {
    int data;
    struct Node *next;
};

// 创建链表节点
struct Node n1 = {10, NULL};
struct Node n2 = {20, &n1};  // n2指向n1

// 访问n2的下一个节点的数据
printf("Next data: %d\n", n2.next->data);  // 输出10

六、结构体与typedef结合

1. 简化结构体类型名
// 传统定义
struct Point {
    int x;
    int y;
};
struct Point p1;  // 使用时必须带struct关键字

// 使用typedef简化
typedef struct {
    int x;
    int y;
} Point;  // 定义别名Point
Point p2;  // 直接使用别名,无需struct关键字
2. 为已有结构体创建别名
struct Rectangle {
    int width;
    int height;
};

typedef struct Rectangle Rect;  // 为struct Rectangle创建别名Rect
Rect r = {10, 20};
3. 结构体指针与typedef
typedef struct {
    char name[20];
    int age;
} Person;

typedef Person* PersonPtr;  // 定义结构体指针别名

Person p = {"Alice", 20};
PersonPtr ptr = &p;  // 等价于struct Person* ptr = &p;
4. 在结构体中自引用
typedef struct Node {
    int data;
    struct Node* next;  // 注意:此处必须用struct Node,不能用Node
} Node;

Node* createNode(int data) {
    Node* newNode = (Node*)malloc(sizeof(Node));
    newNode->data = data;
    newNode->next = NULL;
    return newNode;
}
5. 嵌套结构体与typedef
typedef struct {
    int day;
    int month;
    int year;
} Date;

typedef struct {
    char name[30];
    Date birthdate;  // 嵌套使用Date类型
} Employee;

// 初始化示例
Employee e = {
    "Bob",
    {15, 5, 1990}
};

七、结构体的内存对齐

结构体的内存布局会受对齐规则影响:

struct Example {
    char a;     // 1字节
    int b;      // 4字节(通常对齐到4字节边界)
    short c;    // 2字节
}; // 总大小通常为12字节(非8字节)

八、常见错误与注意事项

结构体相关
  1. 未初始化成员
struct Data d;
printf("%d", d.value); // 未定义行为
  1. 结构体赋值
struct Point a = {1,2};
struct Point b = a; // 合法:整体赋值

 

枚举相关
  1. 超出范围的值
enum Level {LOW, MEDIUM, HIGH};
enum Level x = (enum Level)5; // 编译通过,但危险

  1. 整数与枚举的转换
enum Color c = 2; // 隐式转换(不推荐)

九、完整示例:结构体引用综合应用

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

// 定义结构体
struct Book {
    char title[50];
    float price;
    struct {
        char author[30];
        int year;
    } info;  // 嵌套结构体
};

// 函数:通过指针设置图书信息
void setBook(struct Book *b, const char *title, float price, 
             const char *author, int year) {
    strcpy(b->title, title);
    b->price = price;
    strcpy(b->info.author, author);
    b->info.year = year;
}

// 函数:打印图书信息
void printBook(struct Book b) {
    printf("Title: %s\n", b.title);
    printf("Author: %s\n", b.info.author);
    printf("Year: %d\n", b.info.year);
    printf("Price: $%.2f\n", b.price);
}

int main() {
    struct Book b1;
    setBook(&b1, "C Programming", 29.99, "John Doe", 2021);
    
    // 直接修改成员
    b1.price = 34.99;
    
    // 打印信息
    printBook(b1);
    
    return 0;
}
posted @ 2025-06-27 13:27  RaLi  阅读(2)  评论(0)    收藏  举报  来源