0. 结构体指针
与整数指针、数组指针和函数指针一样,我们也有结构体指针或结构体指针。
struct records {char name[20];int roll;int marks[5];char gender;
};struct records student = {"Alex", 43, {76, 98, 68, 87, 93}, 'M'};struct records *ptrStudent = &student;
在这里,我们声明了一个ptrStudent类型为 的指针struct records。student我们已将的地址分配给ptrStudent。
ptrStudent存储 的基地址student,它是结构体第一个成员的基地址。增加 1 将使地址增加sizeof(student)字节。
printf("Address of structure = %d\n", ptrStudent);
printf("Adress of member `name` = %d\n", &student.name);
printf("Increment by 1 results in %d\n", ptrStudent + 1);/* Output */
Address of structure = 6421984
Adress of member `name` = 6421984
Increment by 1 results in 6422032
我们可以通过两种方式访问studentusing的成员。ptrStudent使用我们的老朋友*或使用->(中缀或箭头运算符)。
对于*,我们将继续使用.( 点运算符),而对于 ,->我们将不需要点运算符。
printf("Name w.o using ptrStudent : %s\n", student.name);
printf("Name using ptrStudent and * : %s\n", ( *ptrStudent).name);
printf("Name using ptrStudent and -> : %s\n", ptrStudent->name);/* Output */
Name without using ptrStudent: Alex
Name using ptrStudent and *: Alex
Name using ptrStudent and ->: Alex
同样,我们也可以访问和修改其他成员。请注意,使用时括号是必需的,*因为点运算符 ( .) 的优先级高于*。
1. 结构体数组
我们可以创建一个类型数组struct records并使用指针来访问元素及其成员。
struct records students[10];/* Pointer to the first element ( structure) of the array */
struct records *ptrStudents1 = &students;/* Pointer to an array of 10 struct records */
struct records (*ptrStudents2)[10] = &students;
请注意,ptrStudent1是 一个指向student[0]while的指针,而ptrStudent2是一个指向整个数组 10 的指针struct records。加 1 将ptrStudent1指向student[1]。
我们可以使用ptrStudent1循环来遍历元素及其成员。
for( int i = 0; i < 10; i++)
printf("%s, %d\n", ( ptrStudents1 + i)->name, ( ptrStudents1 + i)->roll);
2. 将结构指针作为参数
我们还可以将结构变量的地址传递给函数。
#include <stdio.h>struct records {char name[20];int roll;int marks[5];char gender;
};main(){struct records students = {"Alex", 43, {76, 98, 68, 87, 93},
'M'};printRecords(&students);
}void printRecords( struct records *ptr){printf("Name: %s\n", ptr->name);printf("Roll: %d\n", ptr->roll);printf("Gender: %c\n", ptr->gender);for( int i = 0; i < 5; i++)printf("Marks in %dth subject: %d\n", i, ptr->marks[i]);
}/* Output */
Name: Alex
Roll: 43
Gender: M
Marks in 0th subject: 76
Marks in 1th subject: 98
Marks in 2th subject: 68
Marks in 3th subject: 87
Marks in 4th subject: 93
请注意,该结构struct records是在外部声明的main()。这是为了确保它在全球范围内可用并且printRecords()可以使用。
如果该结构体在内部定义main(),其范围将被限制为main(). 此外,结构体也必须在函数声明之前声明。
与结构一样,我们可以拥有指向联合的指针,并且可以使用箭头运算符 (
->) 访问成员。
3. 指针到指针
到目前为止,我们已经了解了指向各种原始数据类型、数组、字符串、函数、结构和联合的指针。
我自然而然地想到的问题是——指针到指针怎么样?
好消息给你!他们也存在。
int var = 6;
int *ptr_var = &var;printf("Address of var = %d\n", ptr_var);
printf("Address of ptr_var = %d\n", &ptr_var);/* Output */
Address of var = 6422036
Address of ptr_var = 6422024
int为了存储变量的地址var,我们有一个指向 的指针int ptr_var。我们需要另一个指针来存储 的地址ptr_var。
由于ptr_var是 类型int *,为了存储其地址,我们必须创建一个指向 的指针int *。下面的代码展示了如何做到这一点。
int * *ptr_ptrvar = &ptr_var; /* or int* *ppvar or int **ppvar */
我们可以使用ptr_ptrvar来访问 的地址ptr_var,并使用双重解引用来访问 var。
printf("Address of ptr_var = %d\n", ptr_ptrvar);
printf("Address of var = %d\n", *ptr_ptrvar);
printf("Value at var = %d\n", *(*ptr_ptrvar));/* Output */
Address of ptr_var = 6422024
Address of var = 6422036
Value at var = 6
取消引用时不需要使用括号ptr_ptrvar。但使用它们是一个很好的做法。我们可以创建另一个指针ptr_ptrptrvar,它将存储 的地址ptr_ptrvar。
由于ptr_ptrvar是 类型int**,因此声明ptr_ptrptrvar为
int** *ptr_ptrptrvar = &ptr_ptrvar;
我们可以再次访问ptr_ptrvar并ptr_var使用。varptr_ptrptrvar
printf("Address of ptr_ptrvar = %d\n", ptr_ptrptrvar);
printf("Value at ptr_ptrvar = %d\n",*ptr_ptrptrvar);
printf("Address of ptr_var = %d\n", *ptr_ptrptrvar);
printf("Value at ptr_var = %d\n", *(*ptr_ptrptrvar));
printf("Address of var = %d\n", *(*ptr_ptrptrvar));
printf("Value at var = %d\n", *(*(*ptr_ptrptrvar)));/* Output */
Address of ptr_ptrvar = 6422016
Value at ptr_ptrvar = 6422024
Address of ptr_var = 6422024
Value at ptr_var = 6422036
Address of var = 6422036
Value at var = 6
ptr_ptrptrvar如果我们使用或更改任何指针的值ptr_ptrvar,则指针将停止指向该变量。
我尝试尽可能多地介绍指针。我们讨论了指针表示法、定义、类型和算术。接下来是它在数组、字符串和函数中的使用。最后,我们讨论了结构体和指针本身!一个完整的圆,不是吗?