4. 指针运算
4.1 指针+-整数
1. #include<stdio.h> 2. int main() 3. { 4. int arr[10] = { 0,1,2,3,4,5,6,7,8,9 }; 5. 6. int sz = sizeof(arr) / sizeof(arr[0]); 7. int i = 0; 8. for (i = 0; i < sz; i++) 9. { 10. printf("%d ", arr[i]); 11. } 12. printf("\n"); 13. int* p = NULL; 14. p = &arr; 15. for (i = 0; i < sz; i++) 16. { 17. printf("%d ", *(p + i)); 18. } 19. 20. return 0; 21. }
结合前面的内容应该可以看的明白。
4.2 指针-指针
1. #include<stdio.h> 2. int main() 3. { 4. 5. int arr[10] = { 0 }; 6. printf("%d\n", &arr[9] - &arr[0]); 7. 8. int* p = NULL; 9. p = &arr[9]; 10. int* q = NULL; 11. q = &arr[0]; 12. printf("%d\n", p - q); 13. 14. 15. 16. 17. return 0; 18. }
指向同一块空间的指针才有意义,指针减指针的绝对值是指针之间的元素个数!!!
注意:指针相加没有意义
4.3 指针的关系运算
(比较大小)
1. #define N_VALUES 5 2. float values[N_VALUES]; 3. float *vp; 4. for(vp = &values[N_VALUES]; vp > &values[0];) 5. { 6. *--vp = 0; 7. }
代码简化, 这将代码修改如下:
1. #define N_VALUES 5 2. float values[N_VALUES]; 3. float *vp; 4. for(vp = &values[N_VALUES-1]; vp >= &values[0];vp--) 5. { 6. *vp = 0; 7. }
实际在绝大部分的编译器上是可以顺利完成任务的,然而我们还是应该避免这样写,因为标准并不保证它可行
标准规定:
允许指向数组元素的指针与指向数组最后一个元素后面的那个内存位置的指针比较,但是不允许与
指向第一个元素之前的那个内存位置的指针进行比较。
5. 指针和数组
我们看一个例子:
1. #include <stdio.h> 2. int main() 3. { 4. int arr[10] = {1,2,3,4,5,6,7,8,9,0}; 5. printf("%p\n", arr); 6. printf("%p\n", &arr[0]); 7. return 0; 8. }
可见数组名和数组首元素的地址是一样的。
结论:数组名表示的是数组首元素的地址。(2种情况除外,数组章节讲解了)
那么这样写代码是可行的:
1. int arr[10] = {1,2,3,4,5,6,7,8,9,0}; 2. int *p = arr;//p存放的是数组首元素的地址
既然可以把数组名当成地址存放到一个指针中,我们使用指针来访问一个就成为可能。
例如:
1. #include <stdio.h> 2. int main() 3. { 4. int i = 0; 5. int arr[] = { 1,2,3,4,5,6,7,8,9,0 }; 6. int* p = arr; //指针存放数组首元素的地址 7. int sz = sizeof(arr) / sizeof(arr[0]); 8. for (i = 0; i < sz; i++) 9. { 10. printf("&arr[%d] = %p <====> p+%d = %p\n", i, &arr[i], i, p + i); 11. } 12. return 0; 13. }
所以 p+i 其实计算的是数组 arr 下标为i的地址。
那我们就可以直接通过指针来访问数组。
如下:
1. int main() 2. { 3. int arr[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 0 }; 4. int* p = arr; //指针存放数组首元素的地址 5. int sz = sizeof(arr) / sizeof(arr[0]); 6. int i = 0; 7. for (i = 0; i < sz; i++) 8. { 9. printf("%d ", *(p + i)); 10. } 11. return 0; 12. }
6. 二级指针
指针变量也是变量,是变量就有地址,那指针变量的地址存放在哪里?
这就是二级指针。
对于二级指针的运算有:
*ppa 通过对ppa中的地址进行解引用,这样找到的是 pa , *ppa 其实访问的就是 pa .
1. int b = 20; 2. *ppa = &b;//等价于 pa = &b;
**ppa 先通过 *ppa 找到 pa ,然后对 pa 进行解引用操作: *pa ,那找到的是 a .
1. **ppa = 30; 2. //等价于*pa = 30; 3. //等价于a = 30;
7. 指针数组
指针数组是指针还是数组?
答案:是数组。是存放指针的数组。
数组我们已经知道整形数组,字符数组。
1. int arr1[5]; 2. char arr2[6];
那指针数组是怎样的?
int* arr3[5];//是什么?
arr3是一个数组,有五个元素,每个元素是一个整形指针。
这样我们在用到多个指针的时候利用指针数组将会更加方便!