本文会非常简单地说明指针是在干嘛,什么时候用,怎么去用,不会涉及复杂的&*()混搭最后问类型的奇怪例子。
指针是在干嘛举个简单的例子:
你把你的小秘密写了一个纸条,放进了一个盒子,你打开这个盒子就可以看到小纸条,这是一种直接访问内存中数据的方式,也是我们最一般的数据访问方式。
你现在有很多盒子,有的盒子有一些小纸条,上面写着你的小秘密,另一些盒子写着你要去哪里找到这些有小纸条的盒子,这样,你就可以先找到有地址的盒子,再根据这个地址去找到你的小秘密。
那么,写着地址的小纸条也是小纸条,装着地址的盒子也是一个盒子,我们是不是可以有另一个盒子,装着一个纸条,上面有个地址,打开之后发现里面的纸条依旧写着地址,再继续下去,依旧写着地址……最后找到一个小秘密呢。
可以,这就是多级指针,C语言运行你这样套娃,但我们不建议过度套娃,要自行承担看不懂程序的后果。
函数传参用指针有三个好处
- 性能更好。可以理解为,别人向你要某个盒子里装的的大笨书的内容,但那个书很大很厚,复印一件的话费时费力,于是你选择给了一个编号,谁要看的话自己去这个地方查。这个编号就是指针。
void printLargeObject(LargeObject *l)
{
//在函数内不会复制出一个LargeObject,
//而是通过指针l直接访问对应的空间
//...
}
类型更灵活。本来,别人需要告诉我们,他要的是哪类书,不是这类书不要。但现在呢,你可以只给一个位置,类型不重要,是不是需要的那一类书,谁要的谁自己去判断。这个就是C++多态思想的雏形,在C语言中涉及函数指针的参数偏多,这里略过。可以直接改掉原本的数据。本来,别人拿到的是复印件,在复印件上勾勾画画,不影响原件,现在你给了他原件的位置,他就可以在原件上勾勾画画,虽然增大了风险,但也更方便了。void AddOne(int *a)
{
*a = *a + 1; //函数外面传入的a指向的整数被加了1
}
排序交换用指针的好处,不言而喻,性能好,还是两本大笨书,要交换位置得抱出来,再放进另一个位置去,中间还得有个桌子暂时搁一下这两本书。现在呢,只需要交换写着两本书位置的小纸条,一下子轻松了很多。
void swap(void* a, void* b){
void* temp = a;
a = b;
b = temp;
}
通过一个地址,不只可以找到这一个小盒子,还可以找到后面的n个小盒子,这样就给我们提供了极大的方便,这n个小盒子里面可以放任何东西,可以放整数,可以放浮点数,也可以放其他变量的地址,而且空间可以很大很大,极大地提高了灵活性。
int* arrptr = (int*)malloc(10 * sizeof(int)); arrptr[0] = 0; //像数组一样使用 arrptr[9] = 9;
有些地方不得不用,例如qsort函数的比较函数,人家都要求用了,你想偷懒直接调函数,自然就得学会怎么用指针。例子见:
手把手,最详细 | C语言调用qsort函数对struct结构体排序
- 理解指针的类型:指针用type *来表示,type为C语言中的类型:例如,int,float,void,char,也可以是自己定义的结构体类型等。定义一个int* a = NULL,就是创建了一个指向整数的int*变量。int*的含义是内部存储的值是一个地址,并且访问地址中的数据的方式是按int访问。理解指针的访问:上面的a,就代表一个地址,而*a,就是访问其中的值。理解地址的含义:之前学过,如果定义了一个int b,那么&b就代表b的地址,所以可以把&b赋值给指针d:int* d = &b。理解结构体指针的访问:结构体指针访问其属性,可以用箭头:c->num,相当于(*c).num。理解指针和数组的关系:
数组 到 指针:数组的变量名即为这一段空间的起始地址,也可以把这个值赋给一个指针。
int arr[10]; int * arrptr = arr;指针 到 数组:指针指向了一片已开辟的空间,可以像数组一样来使用。
int* arrptr = (int*)malloc(10 * sizeof(int)); arrptr[0] = 0; //像数组一样使用 arrptr[9] = 9; arrptr[10] = 10; //访问越界 free(arrptr);



