|
1 | 1 | --- |
2 | 2 | sidebar_position: 12 |
3 | | -title: (编写中)结构和其他数据形式 |
| 3 | +title: (编写中)⭐结构和其他数据形式 |
4 | 4 | --- |
5 | 5 |
|
6 | | - |
7 | 6 | ## 结构体 |
8 | 7 |
|
| 8 | +结构体是C语言中组织相关数据的核心机制,在Python-C互操作中用于: |
| 9 | +- 定义复杂的数据结构 |
| 10 | +- 与Python类进行映射 |
| 11 | +- 高效传递多个相关数据 |
| 12 | + |
| 13 | +### 基本结构体定义 |
| 14 | +```c |
| 15 | +// 定义结构体 |
| 16 | +struct Person { |
| 17 | + char name[50]; |
| 18 | + int age; |
| 19 | + float height; |
| 20 | +}; |
| 21 | + |
| 22 | +// 使用typedef简化 |
| 23 | +typedef struct { |
| 24 | + char name[50]; |
| 25 | + int age; |
| 26 | + float height; |
| 27 | +} Person; |
| 28 | + |
| 29 | +// 声明变量 |
| 30 | +Person p1; |
| 31 | +Person *p2 = malloc(sizeof(Person)); |
| 32 | +``` |
| 33 | + |
| 34 | +### 结构体初始化和访问 |
| 35 | +```c |
| 36 | +// 初始化 |
| 37 | +Person p1 = {"张三", 25, 175.5}; |
| 38 | +Person p2 = {.name = "李四", .age = 30, .height = 180.0}; |
| 39 | + |
| 40 | +// 访问成员 |
| 41 | +printf("姓名: %s\n", p1.name); |
| 42 | +printf("年龄: %d\n", p1.age); |
| 43 | + |
| 44 | +// 指针访问 |
| 45 | +Person *ptr = &p1; |
| 46 | +printf("身高: %.1f\n", ptr->height); |
| 47 | +``` |
| 48 | +
|
| 49 | +### 结构体嵌套 |
| 50 | +```c |
| 51 | +typedef struct { |
| 52 | + int year; |
| 53 | + int month; |
| 54 | + int day; |
| 55 | +} Date; |
| 56 | +
|
| 57 | +typedef struct { |
| 58 | + char name[50]; |
| 59 | + Date birthdate; |
| 60 | + float salary; |
| 61 | +} Employee; |
| 62 | +
|
| 63 | +Employee emp = { |
| 64 | + .name = "王五", |
| 65 | + .birthdate = {1990, 5, 15}, |
| 66 | + .salary = 8000.0 |
| 67 | +}; |
| 68 | +``` |
| 69 | + |
| 70 | +## 联合体 |
| 71 | + |
| 72 | +联合体允许在同一内存位置存储不同的数据类型,在Python-C互操作中用于: |
| 73 | +- 节省内存空间 |
| 74 | +- 实现变体类型 |
| 75 | +- 处理网络协议数据 |
| 76 | + |
| 77 | +### 基本联合体 |
| 78 | +```c |
| 79 | +union Data { |
| 80 | + int i; |
| 81 | + float f; |
| 82 | + char str[20]; |
| 83 | +}; |
| 84 | + |
| 85 | +union Data data; |
| 86 | +data.i = 10; |
| 87 | +printf("data.i: %d\n", data.i); |
| 88 | + |
| 89 | +data.f = 3.14; |
| 90 | +printf("data.f: %.2f\n", data.f); |
| 91 | +``` |
| 92 | +
|
| 93 | +### 带标签的联合体 |
| 94 | +```c |
| 95 | +typedef struct { |
| 96 | + enum { INT, FLOAT, STRING } type; |
| 97 | + union { |
| 98 | + int i; |
| 99 | + float f; |
| 100 | + char str[20]; |
| 101 | + } value; |
| 102 | +} Variant; |
| 103 | +
|
| 104 | +Variant var; |
| 105 | +var.type = INT; |
| 106 | +var.value.i = 42; |
| 107 | +
|
| 108 | +if (var.type == INT) { |
| 109 | + printf("整数值: %d\n", var.value.i); |
| 110 | +} |
| 111 | +``` |
| 112 | + |
| 113 | +## 枚举 |
| 114 | + |
| 115 | +枚举提供有意义的名称来代替数字常量: |
| 116 | + |
| 117 | +```c |
| 118 | +typedef enum { |
| 119 | + RED, // 0 |
| 120 | + GREEN, // 1 |
| 121 | + BLUE // 2 |
| 122 | +} Color; |
| 123 | + |
| 124 | +Color c = GREEN; |
| 125 | +if (c == GREEN) { |
| 126 | + printf("这是绿色\n"); |
| 127 | +} |
| 128 | +``` |
| 129 | + |
| 130 | +## Python-C互操作中的应用 |
| 131 | + |
| 132 | +### 结构体与Python类的映射 |
| 133 | +```c |
| 134 | +// C结构体 |
| 135 | +typedef struct { |
| 136 | + double x; |
| 137 | + double y; |
| 138 | +} Point; |
| 139 | + |
| 140 | +export Point* create_point(double x, double y) { |
| 141 | + Point *p = malloc(sizeof(Point)); |
| 142 | + p->x = x; |
| 143 | + p->y = y; |
| 144 | + return p; |
| 145 | +} |
| 146 | + |
| 147 | +export double point_distance(Point *p1, Point *p2) { |
| 148 | + double dx = p1->x - p2->x; |
| 149 | + double dy = p1->y - p2->y; |
| 150 | + return sqrt(dx*dx + dy*dy); |
| 151 | +} |
| 152 | +``` |
| 153 | +
|
| 154 | +```python |
| 155 | +# Python包装类 |
| 156 | +from ctypes import Structure, c_double, CDLL, POINTER |
| 157 | +
|
| 158 | +class Point(Structure): |
| 159 | + _fields_ = [("x", c_double), ("y", c_double)] |
| 160 | +
|
| 161 | +lib = CDLL('./geometry.so') |
| 162 | +lib.create_point.argtypes = [c_double, c_double] |
| 163 | +lib.create_point.restype = POINTER(Point) |
| 164 | +lib.point_distance.argtypes = [POINTER(Point), POINTER(Point)] |
| 165 | +lib.point_distance.restype = c_double |
| 166 | +
|
| 167 | +# 使用 |
| 168 | +p1 = lib.create_point(1.0, 2.0) |
| 169 | +p2 = lib.create_point(4.0, 6.0) |
| 170 | +distance = lib.point_distance(p1, p2) |
| 171 | +print(f"距离: {distance}") |
| 172 | +``` |
| 173 | + |
| 174 | +### 复杂数据结构的传递 |
| 175 | +```c |
| 176 | +// 图像数据结构 |
| 177 | +typedef struct { |
| 178 | + int width; |
| 179 | + int height; |
| 180 | + int channels; |
| 181 | + unsigned char *data; |
| 182 | +} Image; |
| 183 | + |
| 184 | +export void process_image(Image *img) { |
| 185 | + // 处理图像数据 |
| 186 | + for (int i = 0; i < img->width * img->height * img->channels; i++) { |
| 187 | + img->data[i] = 255 - img->data[i]; // 反色处理 |
| 188 | + } |
| 189 | +} |
| 190 | +``` |
| 191 | + |
| 192 | +## 内存布局和对齐 |
| 193 | + |
| 194 | +### 结构体大小和对齐 |
| 195 | +```c |
| 196 | +#include <stdio.h> |
| 197 | + |
| 198 | +typedef struct { |
| 199 | + char a; // 1字节 |
| 200 | + int b; // 4字节 |
| 201 | + short c; // 2字节 |
| 202 | +} Example; |
| 203 | + |
| 204 | +int main() { |
| 205 | + printf("Sizeof Example: %zu\n", sizeof(Example)); |
| 206 | + printf("Offset of a: %zu\n", offsetof(Example, a)); |
| 207 | + printf("Offset of b: %zu\n", offsetof(Example, b)); |
| 208 | + printf("Offset of c: %zu\n", offsetof(Example, c)); |
| 209 | + return 0; |
| 210 | +} |
| 211 | +``` |
| 212 | +
|
| 213 | +### 手动内存对齐 |
| 214 | +```c |
| 215 | +// 确保结构体按8字节对齐 |
| 216 | +typedef struct __attribute__((aligned(8))) { |
| 217 | + char a; |
| 218 | + int b; |
| 219 | + short c; |
| 220 | +} AlignedExample; |
| 221 | +``` |
| 222 | +
|
| 223 | +## 最佳实践 |
| 224 | +
|
| 225 | +1. **使用typedef**:简化结构体类型名称 |
| 226 | +2. **初始化所有字段**:避免未初始化数据 |
| 227 | +3. **考虑内存布局**:合理安排字段顺序减少填充 |
| 228 | +4. **文档化结构体**:说明每个字段的用途和单位 |
| 229 | +5. **验证输入数据**:在Python-C边界进行数据验证 |
| 230 | +
|
| 231 | +## 常见陷阱 |
| 232 | +
|
| 233 | +1. **内存对齐问题**:不同平台对齐要求可能不同 |
| 234 | +2. **字节序问题**:网络传输时需要注意字节序 |
| 235 | +3. **填充字节**:结构体中的填充字节可能导致数据不一致 |
| 236 | +4. **指针生命周期**:确保C中分配的内存在Python中正确管理 |
9 | 237 |
|
10 | | -## 联合体 |
| 238 | +结构体和联合体是C语言中组织数据的强大工具,在Python-C互操作中尤为重要。正确使用它们可以创建高效、类型安全的数据接口。 |
0 commit comments