C语言指针
JDSZGLLL 人气:0前言
经过了指针的初步学习,我们了解了指针有以下特点:
1. 指针就是个变量,用来存放地址,地址唯一标识一块内存空间。
2. 指针的大小是固定的4/8个字节(32位平台/64位平台)。
3. 指针是有类型,指针的类型决定了指针的+-整数的步长,指针解引用操作的时候的权限。
4. 指针的运算。
今天将要从各种不同的指针的角度切入,使得我们对指针的了解更加深入。
字符指针
我们现在已经学会下面的这种指针的使用了:
int main() { char ch = 'w'; char* pc = &ch; *pc = 'w'; return 0; }
通过这段代码,把字符变量ch的地址赋给了pc,同时pc的类型是char*。
接下来让我们来看一看另一段代码:
int main() { const char* pstr = "hello bit.";//这里是把一个字符串放到pstr指针变量里了吗? printf("%s\n", pstr); return 0; }
我们看到,这里是把一个字符串常量和指针pstr关联起来了。并且无论有没有加const,常量的内容是不能改变的。
int main() { char* pstr = "hello bit.";//这里是把一个字符串放到pstr指针变量里了吗? *pstr = 'w'; printf("%s\n", pstr); return 0; }
当我们如上图代码一样,试图改变常量字符串时就会报错:
让我们来通过下面的代码了解内部的逻辑:
int main() { char str1[] = "hello world."; char str2[] = "hello world."; const char *str3 = "hello world."; const char *str4 = "hello world."; if(str1 ==str2) printf("str1 and str2 are same\n"); else printf("str1 and str2 are not same\n"); if(str3 ==str4) printf("str3 and str4 are same\n"); else printf("str3 and str4 are not same\n"); return 0; }
根据代码和运行结果,我们可以知道指针指向的常量字符串的地址是相同的,但把字符串赋予数组时,地址不同,让我们用图来描述这个过程。
同时str1,str2,str3,str4,指的都是字符串首字符的地址。
指针数组
指针数组的本质是数组,只是在数组中存放的内容是指针变量。
接下来让我们看看指针数组长什么样:
int* arr1[10]; //整形指针的数组 char *arr2[4]; //一级字符指针的数组 char **arr3[5];//二级字符指针的数组
指针数组可以类比普通数组,比如:
我们可以发现,指针数组和普通数组的区别仅仅是数组中储存的元素类型不一样,所以说指针数组本质上还是数组。
数组指针
说完了指针数组,让我们来了解一下数组指针 ,数组指针本质上是一个指针。接下来让我们类比一下数组指针和我们常见的指针:
让我们通过一段代码来深入了解 数组指针的特点:
int main() { int arr[10] = { 0 }; printf("arr = %p\n", arr); printf("&arr= %p\n", &arr); printf("arr+1 = %p\n", arr + 1); printf("&arr+1= %p\n", &arr + 1); return 0; }
通过学习我们知道arr是数组首元素的地址,&arr是整个数组的地址,可类比为普通指针和数组指针。
函数指针
函数指针就是存放函数地址的指针 ,通过函数指针可以调用相应的函数。
void test() { printf("hehe\n"); } int main() { printf("%p\n", test); printf("%p\n", &test); return 0; }
通过这段代码我们了解到,函数是有地址的,那怎么把这个地址赋予指针呢?
void test() { printf("hehe\n"); } int main() { printf("%p\n", test); printf("%p\n", &test); void (*p)() = test; (*p)(); return 0; }
以上代码让我们知道了,函数是可以通过指针调用的。
加载全部内容