指针是C语言的精髓,想要学好C语言,就要先掌握指针。
我们先来看指针的初始化。
int a = 5;
int *p = &a; // 将a的地址赋值给p
p = &a; // 与上式等价
这是最基本的初始化操作。指针的实质是地址,通过地址来寻找指向的值。a的值改变,则*p也跟着改变,但p的值不会变,因为p为地址。
int *p = (int *)malloc(sizeof(int)); // 手动分配空间
*p = 7; // 因为*p在内存上分配了空间,可以直接赋值
scanf("%d",p); // 也可以通过输入来给*p赋值
同时我们也可以通过calloc, malloc函数给指针开辟空间。注意:若要对指针进行直接赋值(不是指向某个内存单元),则必须要给指针开辟空间。
接下来我们来看字符指针
char *p = "i love pointer"; // 直接赋值字符串
printf("%s", p); // 打印字符串
while(*p!='\0')
{
int i = 0;
printf("%c", *p++);
printf("%c", p[i++]);
// 两种方式都可以逐个打印*p中的每个元素
}
由于字符串在内存中实际存储的是一片连续的地址,所以我们在这里赋值时,直接赋值字符串即可。
与数组的联系
int arr[3] = {1, 2, 3};
int *p = arr;
数组名作为参数存放的是数组的首地址,与指针的存储形式一样,可以将指针理解成动态数组,因为指针的空间可以重新开辟。
接下来是二级指针。二级指针本质上存储的也是地址,不过在每个空间存储的是一级指针的地址,也就是每个内存空间指向一个一级指针。这个概念类似于二维数组,你可以把二级指针当作二维数组来理解。
char **p;
char a[3][2] = {{'a', 'b', 'c'}, {'d', 'e', 'f'}};
p = (char**)a; // 需要对数组类型进行强转
a存储的是数组的首地址,则我们将a赋值给**p,则p指向数组a的首地址。
char *str[3] = {"stephen", "kevin", "klay"};
char **p = str;
printf("%s\n", *p); // "stephen"
printf("%s\n", *(p+1)); // "kevin"
printf("%c\n", *(*p+1)); // 't'
printf("%c\n", *(*(p+2)+1)); // 'l'
首先我们创建了一个字符串数组,即数组里每个元素为一级指针变量,存放字符串。接着我们新建一个二级指针指向这个数组。首先要弄清楚的是在二级指针中,p存放的是str的首地址,即 p == str; *p存放的是每个字符串的首地址,**p为*p上的存放的地址的值。简单化了个图帮助大家理解。

*p为地址,指向"stephen"。*(p+1)为首地址+1的内存空间的内容,指向"kevin"。*(*p+1)为地址*p+1指向的值‘t’。*(p+2)为地址为p+2的内存块指向的地址,该地址指向的内容为”klay“,*(*(p+2)+1)则为该连续空间的第二块指向的值'l'。
最后需要注意的是(*p)[n]和*p[n]是不同的。()规定了优先级,前者为指向数组的指针,后者为含有多个指针的指针数组,需要注意这两个的区别。
第一次写技术博客,有些的不好的请见谅。欢迎各位的阅读和学习,若有错误,欢迎指正。谢谢大家!

2465

被折叠的 条评论
为什么被折叠?



