當涉及到C語言結構體的高級玩法時,有很多有趣和強大的技巧可以應用。下面是10個例子代碼,每個例子都使用了不同的高級結構體技術,包括位字段、嵌套結構體、聯合體、指向結構體的指針等。讓我們逐個來講解這些例子代碼。
- 位字段(Bit Fields)
#include <stdio.h>
struct Flags {
unsigned int flag1 : 1;
unsigned int flag2 : 2;
unsigned int flag3 : 3;
};
int mAIn() {
struct Flags f;
f.flag1 = 1;
f.flag2 = 2;
f.flag3 = 3;
printf("Flag 1: %dn", f.flag1);
printf("Flag 2: %dn", f.flag2);
printf("Flag 3: %dn", f.flag3);
return 0;
}
在這個例子中,我們使用了位字段來定義一個結構體,其中每個成員變量都指定了所占用的位數。這樣可以有效地使用內存,并在結構體中存儲多個布爾標志或其他具有限定范圍的值。
- 嵌套結構體(Nested Structures)
#include <stdio.h>
struct Date {
int day;
int month;
int year;
};
struct Person {
char name[20];
struct Date birthdate;
};
int main() {
struct Person p;
strcpy(p.name, "John Doe");
p.birthdate.day = 1;
p.birthdate.month = 1;
p.birthdate.year = 1990;
printf("Name: %sn", p.name);
printf("Birthdate: %d/%d/%dn", p.birthdate.day, p.birthdate.month, p.birthdate.year);
return 0;
}
在這個例子中,我們定義了一個Date結構體,它包含了日期的日、月和年。然后,我們在Person結構體中嵌套了Date結構體,以表示一個人的姓名和出生日期。
- 聯合體(Unions)
#include <stdio.h>
union Data {
int i;
float f;
char str[20];
};
int main() {
union Data data;
data.i = 10;
printf("Data as integer: %dn", data.i);
data.f = 3.14;
printf("Data as float: %fn", data.f);
strcpy(data.str, "Hello");
printf("Data as string: %sn", data.str);
return 0;
}
聯合體允許在同一塊內存空間中存儲不同類型的數據。在這個例子中,我們定義了一個Data聯合體,它可以存儲整數、浮點數和字符串。通過更改聯合體的成員,我們可以以不同的方式解釋相同的內存塊。
- 指向結構體的指針(Pointers to Structures)
#include <stdio.h>
struct Point {
int x;
int y;
};
void printPoint(struct Point *p) {
printf("Point coordinates: (%d, %d)n", p->x, p->y);
}
int main() {
struct Point p;
struct Point *ptr;
p.x = 10;
p.y = 20;
ptr = &p;
printPoint(ptr);
return 0;
}
在這個例子中,我們定義了一個Point結構體來表示二維平面上的一個點。然后,我們聲明一個指向Point結構體的指針ptr,并將其指向結構體變量p。通過指針,我們可以直接訪問結構體的成員,并將指針傳遞給函數以操作結構體。
- 結構體的自引用(Self-referential Structures)
#include <stdio.h>
struct Node {
int data;
struct Node *next;
};
int main() {
struct Node node1, node2, node3;
node1.data = 10;
node2.data = 20;
node3.data = 30;
node1.next = &node2;
node2.next = &node3;
node3.next = NULL;
struct Node *current = &node1;
while (current != NULL) {
printf("Data: %dn", current->data);
current = current->next;
}
return 0;
}
這個例子展示了結構體的自引用,其中每個結構體節點包含一個數據成員和一個指向下一個節點的指針。通過鏈接多個節點,我們可以創建鏈表的數據結構。
- 函數指針成員(Function Pointer Members)
#include <stdio.h>
struct MathOperations {
int (*add)(int, int);
int (*subtract)(int, int);
};
int add(int a, int b) {
return a + b;
}
int subtract(int a, int b) {
return a - b;
}
int main() {
struct MathOperations math;
math.add = add;
math.subtract = subtract;
int result1 = math.add(5, 3);
int result2 = math.subtract(10, 4);
printf("Addition result: %dn", result1);
printf("Subtraction result: %dn", result2);
return 0;
}
在這個例子中,我們定義了一個MathOperations結構體,其中包含兩個函數指針成員,分別用于執行加法和減法操作。我們將這些函數指針與相應的函數進行關聯,并使用結構體中的函數指針調用函數。
- 動態分配結構體(Dynamic Allocation of Structures)
#include <stdio.h>
#include <stdlib.h>
struct Person {
char name[20];
int age;
};
int main() {
struct Person *person = (struct Person*) malloc(sizeof(struct Person));
if (person == NULL) {
printf("Memory allocation failed.n");
return 1;
}
strcpy(person->name, "John Doe");
person->age = 25;
printf("Name: %sn", person->name);
printf("Age: %dn", person->age);
free(person);
return 0;
}
在這個例子中,我們使用`malloc`函數動態地分配了一個`Person`結構體的內存空間。通過`sizeof`運算符確定所需的內存大小。然后,我們可以像使用普通結構體一樣,訪問和操作這個動態分配的結構體。最后,記得使用`free`函數釋放動態分配的內存空間,以避免內存泄漏。
- 結構體數組(Array of Structures)
#include <stdio.h>
struct Student {
char name[20];
int age;
float gpa;
};
int main() {
struct Student students[3];
for (int i = 0; i < 3; i++) {
printf("Enter name for student %d: ", i+1);
scanf("%s", students[i].name);
printf("Enter age for student %d: ", i+1);
scanf("%d", &students[i].age);
printf("Enter GPA for student %d: ", i+1);
scanf("%f", &students[i].gpa);
}
printf("nStudent Details:n");
for (int i = 0; i < 3; i++) {
printf("Name: %sn", students[i].name);
printf("Age: %dn", students[i].age);
printf("GPA: %.2fn", students[i].gpa);
printf("n");
}
return 0;
}
在這個例子中,我們定義了一個Student結構體,包含學生的姓名、年齡和GPA。然后,我們創建一個包含3個Student結構體的數組,并使用循環依次獲取每個學生的信息。最后,我們遍歷結構體數組,并打印每個學生的詳細信息。
- 結構體的對齊(Structure Padding)
#include <stdio.h>
#pragma pack(1)
struct Person {
char name[20];
int age;
};
int main() {
struct Person p;
printf("Size of struct Person: %dn", sizeof(p));
return 0;
}
在這個例子中,我們使用#pragma pack(1)預處理指令告訴編譯器以字節對齊方式為1來定義結構體。默認情況下,編譯器會進行結構體成員的對齊,以優化訪問速度。通過指定對齊方式為1,我們可以減少內存浪費,但可能會導致訪問效率稍微降低。我們可以使用sizeof運算符來查看對齊后的結構體大小。
- 結構體作為函數的返回值(Structure as Return Type)
#include <stdio.h>
#include <stdlib.h>
struct Point {
int x;
int y;
};
struct Point* getPoint() {
struct Point* p = malloc(sizeof(struct Point));
p->x = 10;
p->y = 20;
return p;
}
int main() {
struct Point* result = getPoint();
printf("Point coordinates: (%d, %d)n", result->x, result->y);
free(result);
return 0;
}
在這個例子中,我們定義了一個返回`Point`結構體的函數`getPoint()`。在函數內部,我們創建一個`Point`結構體并設置其坐標值。然后,我們將該結構體作為函數的返回值返回,并在`main()`函數中接收并打印返回的結構體的坐標值。我們將getPoint()函數的返回類型改為指向Point結構體的指針。在函數內部,我們使用malloc()動態分配了一個Point結構體的內存,并設置其坐標值。然后,我們返回指向動態分配內存的指針。在main()函數中,我們接收返回的指針,并使用箭頭運算符訪問結構體的成員。最后,記得使用free()函數釋放動態分配的內存空間,以避免內存泄漏。
這些例子展示了C語言結構體的一些高級玩法,包括位字段、嵌套結構體、聯合體、指向結構體的指針、自引用、函數指針成員、動態分配、結構體數組、結構體的對齊以及結構體作為函數的返回值。這些技巧可以幫助你更靈活和高效地使用結構體來組織和操作數據。