C++知识总结-薛老师主讲

C语言结构体

C语言中关于结构体的关键知识点总结:

1. 结构体定义

基本语法:使用struct关键字定义结构体类型,结构体内可以包含多个不同类型的成员。
示例:struct Person { char name[50]; int age; };

2. 结构体变量声明

单独声明:在结构体类型定义后,可以声明该类型的变量。
示例:struct Person person1;
同时声明和定义:在定义结构体的同时声明变量。
示例:struct Person { char name[50]; int age; } person1;

3. 结构体成员访问

通过结构体变量:使用.操作符访问结构体成员。
示例:person1.name = “Alice”;
通过结构体指针:使用->操作符访问结构体成员。
示例:struct Person *p = &person1; p->name = “Bob”;

4. 结构体数组与指针

结构体数组:可以声明结构体类型的数组,用于存储多个结构体实例。
示例:struct Person people[10];
结构体指针数组:数组元素为指向结构体的指针。
示例:struct Person *peoplePtr[10];

5. 嵌套结构体

结构体中可以包含其他结构体作为成员。
示例:struct Address { char street[100]; char city[50]; }; struct Employee { char name[50]; int id; struct Address addr; };

6. 结构体作为函数参数与返回值

作为参数:可以将结构体变量或结构体指针作为函数参数传递。
作为返回值:函数可以返回结构体类型或结构体指针类型的值。

7. 结构体内存布局与对齐

内存布局:结构体成员在内存中的排列顺序与定义顺序一致。
对齐:编译器可能会根据平台要求对结构体成员进行对齐,以提高访问效率。

#pragma pack:可以使用编译器特定的指令(如#pragma pack)来控制对齐方式。

8. 位字段(Bit-fields)

结构体中可以定义位字段,用于紧凑地存储数据。
示例:struct PackedData { unsigned int a : 1; unsigned int b : 3; unsigned int c : 4; };

9. 结构体与联合体的区别

结构体:所有成员在内存中占用独立的空间。
联合体(Union):所有成员共享同一块内存空间,同一时间只能存储一个成员的值。

10. 结构体与枚举的结合使用

枚举类型可以作为结构体的成员,用于表示有限数量的选项或状态。
示例:enum Color { RED, GREEN, BLUE }; struct Pixel { enum Color color; int intensity; };

11. 结构体初始化与赋值

初始化:可以在声明结构体变量时直接初始化其成员。
赋值:可以使用赋值语句对结构体成员进行赋值,也可以将一个结构体变量的值赋给另一个同类型的变量。

12. 动态分配结构体内存

可以使用malloc、calloc等函数动态分配结构体所需的内存空间。
使用完动态分配的内存后,应使用free函数释放。
这些知识点涵盖了C语言中结构体的大部分内容,是理解和使用结构体的基础。在实际编程中,结构体的应用非常广泛,特别是在需要组织复杂数据时。

示例1:基本结构体声明和使用

#include <stdio.h>

struct Person {
    char name[50];
    int age;
};

int main() {
    struct Person p1;
    p1.name = "Alice";
    p1.age = 30;
    printf("Name: %s, Age: %d\n", p1.name, p1.age);
    return 0;
}

注意:此示例中的字符串赋值可能在某些编译器上导致警告或错误,因为name数组是通过逐个字符赋值或strcpy函数来初始化的。为了简化,这里直接赋值,但在实际代码中应使用strcpy。

在您的C语言代码中,尝试直接将字符串赋值给字符数组 p1.name 的方式是错误的。在C语言中,数组名(如 p1.name)是一个常量指针,指向数组的首元素,您不能直接使用赋值运算符(=)将一个字符串字面量(如 “Alice”)赋给整个数组。字符串字面量通常存储在只读内存段中,而数组 p1.name 是可写的。

要正确地将字符串复制到字符数组中,您应该使用 strcpy 函数(需要包含头文件 )。下面是修改后的代码:

#include <stdio.h>
#include <string.h> // 包含strcpy函数所需的头文件

struct Person {
    char name[50];
    int age;
};

int main() {
    struct Person p1;
    strcpy(p1.name, "Alice"); // 使用strcpy函数复制字符串
    p1.age = 30;
    printf("Name: %s, Age: %d\n", p1.name, p1.age);
    return 0;
}

现在,这段代码应该可以正确编译并运行,输出:

Name: Alice, Age: 30

请注意,使用 strcpy 函数时要确保目标数组有足够的空间来存储源字符串,包括结尾的空字符(\0)。在您的例子中,p1.name 数组的大小为50个字符,足够存储 “Alice” 字符串及其结尾的空字符。

示例2:结构体数组

#include <stdio.h>

struct Book {
    char title[100];
    char author[50];
    float price;
};

int main() {
    struct Book library[3];
    // 初始化
    strcpy(library[0].title, "Book1");
    strcpy(library[0].author, "Author1");
    library[0].price = 29.99;
    // 类似地初始化其他书籍
    // 输出
    for (int i = 0; i < 3; i++) {
        printf("Book %d: %s by %s, Price: $%.2f\n", i+1, library[i].title, library[i].author, library[i].price);
    }
    return 0;
}

注意:这里使用了strcpy来复制字符串到结构体数组的元素中。

示例3:结构体指针

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

struct Student {
    char name[50];
    int id;
};

int main() {
    struct Student *s1;
    s1 = (struct Student*)malloc(sizeof(struct Student));
    strcpy(s1->name, "Bob");
    s1->id = 12345;
    printf("Name: %s, ID: %d\n", s1->name, s1->id);
    free(s1);
    return 0;
}

注意:此示例使用了动态内存分配,因此需要包含stdlib.h头文件,并在使用完结构体后释放内存。

示例4:嵌套结构体

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

struct Address {
    char street[100];
    char city[50];
};

struct Employee {
    char name[50];
    int id;
    struct Address addr;
};

int main() {
    struct Employee emp;
    strcpy(emp.name, "Charlie");
    emp.id = 67890;
    strcpy(emp.addr.street, "123 Main St");
    strcpy(emp.addr.city, "Anytown");
    printf("Employee: %s, ID: %d, Address: %s, %s\n", emp.name, emp.id, emp.addr.street, emp.addr.city);
    return 0;
}

示例5:结构体作为函数参数

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

struct Car {
    char make[50];
    char model[50];
    int year;
};

void printCar(struct Car c) {
    printf("Car: %s %s (%d)\n", c.make, c.model, c.year);
}

int main() {
    struct Car myCar;
    strcpy(myCar.make, "Toyota");
    strcpy(myCar.model, "Camry");
    myCar.year = 2020;
    printCar(myCar);
    return 0;
}

示例6:结构体作为函数返回类型

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

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

struct Date getCurrentDate() {
    struct Date today;
    today.day = 15;
    today.month = 8;
    today.year = 2023;
    return today;
}

int main() {
    struct Date today = getCurrentDate();
    printf("Today's date: %d-%d-%d\n", today.day, today.month, today.year);
    return 0;
}

示例7:结构体比较

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

struct Product {
    char name[50];
    float price;
};

int compareProducts(struct Product p1, struct Product p2) {
    return strcmp(p1.name, p2.name);
}

int main() {
    struct Product apple, banana;
    strcpy(apple.name, "Apple");
    apple.price = 0.99;
    strcpy(banana.name, "Banana");
    banana.price = 0.59;

    if (compareProducts(apple, banana) < 0) {
        printf("Apple comes before Banana alphabetically.\n");
    } else {
        printf("Banana comes before or is the same as Apple alphabetically.\n");
    }
    return 0;
}

示例8:结构体中的位字段

#include <stdio.h>

struct PackedData {
    unsigned int a : 1;
    unsigned int b : 3;
    unsigned int c : 4;
};

int main() {
    struct PackedData pd;
    pd.a = 1;
    pd.b = 6;
    pd.c = 15;
    printf("Packed Data: a=%u, b=%u, c=%u\n", pd.a, pd.b, pd.c);
    return 0;
}

示例9:结构体与联合体(共用体)的区别

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

struct Data1 {
    int i;
    float f;
};

union Data2 {
    int i;
    float f;
};

int main() {
    struct Data1 d1;
    union Data2 d2;

    d1.i = 10;
    d1.f = 9.75;
    printf("Struct: int=%d, float=%f\n", d1.i, d1.f); // 输出两个值

    d2.i = 10;
    d2.f = 9.75;
    printf("Union: int=%d, float=%f\n", d2.i, d2.f); // 只有一个值有效,取决于最后赋值的类型
    return 0;
}

示例10:结构体与枚举结合使用

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

enum Color { RED, GREEN, BLUE };

struct Pixel {
    enum Color color;
    int intensity;
};

int main() {
    struct Pixel p;
    p.color = GREEN;
    p.intensity = 255;
    printf("Pixel color: %d, Intensity: %d\n", p.color, p.intensity);
    return 0;
}