4.2 指针 - 指针
指针 - 指针 = 地址 - 地址
前提:
两个指针指向同一块空间(意味着指针的类型是一致的)
举例:
#include <stdio.h> int main() { int arr[10] = { 0,1,2,3,4,5,6,7,8,9 }; int n = &arr[9] - &arr[0]; printf("%d\n", n); return 0; }
分析:
效果展示:
结论:指针 - 指针得到的是指针和指针之间的元素个数(大地址 - 小地址是正的,小地址 - 大地址是负的)
举例:求字符串长度
这个我们是用计数器的方法写的
#include <stdio.h> int my_strlen(char* str) { int count = 0; while (*str != '\0') { count++; str++; } return count; } int main() { char str[] = "Hello World"; int res = my_strlen(str); printf("%d\n", res); return 0; }
我们接下来使用指针 - 指针的方式来写
#include <stdio.h> int my_strlen(char* str) { char* start = str; while (*str != '\0') { str++; } return str-start; } int main() { char str[] = "Hello World"; int res = my_strlen(str); printf("%d\n", res); return 0; }
效果展示:
这里我们就是用到了结论。
4.3 指针的运算关系
我们来看一段代码:
#define N_VALUES 5 #include <stdio.h> int main() { float values[N_VALUES]; float* vp; for (vp = &values[N_VALUES]; vp > &values[0];) { *--vp = 0; } return 0; }
分析:
上面的代码可读性不高,我们对代码进行改进
#define N_VALUES 5 #include <stdio.h> int main() { float values[N_VALUES]; float* vp; for (vp = &values[N_VALUES-1]; vp >= &values[0]; --vp) { *vp = 0; } return 0; }
分析:
改进后的代码实际在绝大部分的编译器上是可以顺利完成任务的,然而我们还是应该避免这样写,因为标准并不保证它可行。
标准规定:
允许指向数组元素的指针与指向数组最后一个元素后面的那个内存位置的指针比较,但是不允许与指向第一个元素之前的那个内存位置的指针比较。
改进后的代码在循环判断部分是>=,这就存在了首元素的地址与首元素之前的地址进行比较,这样是不可以的。
画图深入理解一下:
5、指针和数组
指针就是指针;数组就是数组。不等同,但是有连系。
我们举例来深入了解:
#include <stdio.h> int main() { int arr[10] = { 0 }; int* p = arr;//&arr[0] - 数组名是首元素地址 int i = 0; for (i = 0; i < 10; i++) { *(p+i) = i + 1; } for (i = 0; i < 10; i++) { printf("%d ", *(p+i)); } return 0; }
效果展示:
Q:为什么可以使用指针对数组赋值呢?
A:
1.指针可以指向数组元素
2.因为指针可以运算,所以借助于指针可以访问数组
6、二级指针
我们来看这段代码:
#include <stdio.h> int main() { int a = 10;//a在内存中申请4个字节的空间 int* pa = &a;//pa是指针变量,用来存放地址,也得向内存申请4/8个字节,因此pa也是有地址的 int** ppa = &pa;//&pa的地址就放在ppa里面,因此ppa就是二级指针 //打印a printf("%d\n", **ppa); return 0; }
效果展示:
分析:
7、指针数组
指针数组是指针还是数组?
答案:是数组。是存放指针的数组。
数组我们已经知道整型数组、字符数组
我们以代码举例:
#include <stdio.h> int main() { int a = 10; int b = 20; int c = 30; //指针数组 - 存放指针数组 int* arr[] = { &a, &b, &c }; //打印 int i = 0; for (i = 0; i < 3; i++) { printf("%d ", *(arr[i])); } return 0; }
效果展示:
分析:
arr[ ]数组是 int* 类型的,说明存放的是指针,这就是指针数组,我们循环打印,对数组的每一位都解引用,就将数字全部打印出来了。
引申:
#include <stdio.h> int main() { char* ch[5]; char** chh = ch; return 0; }
分析: