与整数指针、数组指针和函数指针一样,我们也有结构体指针或结构体指针。
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
我们可以通过两种方式访问student
using的成员。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
同样,我们也可以访问和修改其他成员。请注意,使用时括号是必需的,*
因为点运算符 ( .
) 的优先级高于*
。
我们可以创建一个类型数组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);
我们还可以将结构变量的地址传递给函数。
#include
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()
. 此外,结构体也必须在函数声明之前声明。
与结构一样,我们可以拥有指向联合的指针,并且可以使用箭头运算符 (
->
) 访问成员。
到目前为止,我们已经了解了指向各种原始数据类型、数组、字符串、函数、结构和联合的指针。
我自然而然地想到的问题是——指针到指针怎么样?
好消息给你!他们也存在。
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
使用。var
ptr_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
,则指针将停止指向该变量。
我尝试尽可能多地介绍指针。我们讨论了指针表示法、定义、类型和算术。接下来是它在数组、字符串和函数中的使用。最后,我们讨论了结构体和指针本身!一个完整的圆,不是吗?