指针运算
指针+-整数
//利用数组指针+-整数来遍历数组 #include<stdio.h> int main() { int arr[10] = { 1,2,3,4,5,6,7,8,9,10 }; int* p = arr; int i = 0; for (i = 0; i < 10; i++) { printf("%d\n", *(p+i)); } return 0; }
//利用数组指针+-整数来遍历数组 #include<stdio.h> int main() { int arr[10] = { 1,2,3,4,5,6,7,8,9,10 }; // 0,1,2,3,4,5,6,7,8,9 int* p = arr; int i = 0; for (i = 0; i < 10; i++) { printf("%d\n", *(p+i)); printf("%d\n", *(arr + i)); printf("%d\n", arr[i]); printf("%d\n", i[arr]); //本质和底层逻辑: // 数组遍历元素都是根据(首地址+偏移量)解引用找到数组中的元素 //p指向的是数组首元素 //p+i 是数组中下标为i的元素的地址 //p+i 起始时跳过了i*sizeof(int)个字节 } return 0; } //arr——>p //arr == p //arr+i == p+i //*(arr+i) == *(p+i) == arr[i] //*(arr+i) == arr[i] // //*(i+arr) == i[arr] // [ ]下标应用操作符 // 3+5和5+3 // i[arr]=arr[i]
数组利用下标遍历数组元素本质:
均是拿到数组首元素地址,根据(首元素+偏移量)解引用找到数组中的元素。
[ ]下标应用操作符:arr[i]=i[arr]
指针-指针
#include<stdio.h> int main() { int arr[10] = { 1,2,3,4,5,6,7,8,9,10 }; printf("%d\n", arr[0] - arr[9]); printf("%d", arr[9] - arr[0]); return 0; }
指针-指针的前提:两个指针指向同一块区域,指针类型是相同
指针-指针差值的绝对值:指针和指针之间的元素个数
关于模拟实现strlen的功能,我们学习了计数器和递归,在这里我们将用到指针运算的方法去实现strlen的功能。
#include<stdio.h> size_t str( char* str) { char* p = str; while (*str) //while(*str != '\0') //其实\0就是\ddd 所以\0就是0 while表达式的执行条件是真,为0时跳出括号。 { str++; } return str - p;//地址 } int main() { char arr[] = "abcdef"; size_t ret = str(arr); printf("%zd\n", ret); return 0; } //特殊注意不要将指针变量的类型搞错了
指针的关系运算
#define N_VALUES 5 float values[N_VALUES]; float *vp; //指针+-整数;指针的关系运算 for (vp = &values[0]; vp < &values[N_VALUES];) { *vp++ = 0; }
这段代码是怎样执行的呢?如下
这里我们就vp和&values[N_VALUES]指针间的关系,即指针和指正比较(= > < >= <=)等等
那我们换种写法呢?
#define N_VALUES 5 float values[N_VALUES]; float* vp; for (vp = &values[N_VALUES]; vp > &values[0];) { *--vp = 0; }
这里有些友友会觉得太复杂了,那我们来简化一下。
#define N_VALUES 5 float values[N_VALUES]; float* vp; for (vp = &values[N_VALUES - 1]; vp >= &values[0]; vp--) { *vp = 0; }
虽然这样写很简单,实际上再绝大部分的编译器上是可以顺利完成任务的,然而我们还是应该避免这样写,因为标准不保证它可行。
标准规定:
允许指向数组元素的指针与指向数组最后一个元素后面的那个内存位置的指针比较,但是不允许与指向一个元素之前的那个内存位置的指针进行比较。
那为什么要这样规定呢?在后面学习C++其他的时候应该会解决的我们疑惑吧。
二级指针
指针变量也是变量,是变量就有地址,那指针变量的地址存放在哪里?这就是二级指针。
二级指针变量是存放一级指针变量的地址的。
#include<stdio.h> int main() { int a = 10; int* p = &a;//p是指针变量,一级指针变量 int* * pp = &p;//pp是指针,二级指针变量 return 0; }
特别注意对指针变量的理解,当然还有三级,四级指针等等,那我们常用的就是一级二级指针。
*pp通过对pp中的地址进行解引用,这样找到的是p,pp其实访问的是p
**pp先通过*pp找到p,然后对p进行解引用操作,*p,那就找到了a
*pp--------→p *p---------→a
**pp---------→a
#include<stdio.h> int main() { int a = 10; int * p = &a; int * * pp = &p; **pp = 20; printf("%d", a); return 0; }
指针与数组
指针就是指针,指针变量就是一个变量,存放地址,指针变量的大小是4/8
数组就是数组,可以存放一组类型相同的元素,数组的大小是取决于元素的类型和个数
二者联系:数组的数组名是数组首元素的地址,地址是可以访问指针变量中。
关于数组名,我们再次复习一下
数组名表示首元素地址
sizeof(数组名),数组名单独放在sizeof内部,数组名表示整个数组,计算的是数组的大小,单位是字节。
&数组名,数组名表示整个数组,取出的是数组的地址,数组的地址和数组首元素的地址,值是一样的,但是类型和意义是不一样的。
#include<stdio.h> int main() { int arr[] = { 1,2,3,4,5,6,7,8,9,10 }; printf("%p\n", &arr); printf("%p\n", &arr + 1); //int* 跳过4个字节 printf("%p\n", arr); printf("%p\n", arr + 1); printf("%p\n", &arr[0]); printf("%p\n", &arr[0]+1); printf("%d\n", sizeof(arr)); return 0; }
上面我们已经学习到数组名(首元素地址)和指针变量p(存放首元素地址)可以互换使用。
//arr——>p //arr == p //arr+i == p+i //*(arr+i) == *(p+i) == arr[i] //*(arr+i) == arr[i] #include<stdio.h> int main() { int arr[10] = { 1,2,3,4,5,6,7,8,9,10 }; int* p = arr; int i = 0; for (i = 0; i < 10; i++) { printf("%d\n", *(p + i)); printf("%d\n", *(arr + i)); } return 0; }
特别提醒:
p是一个指针变量可以++/--等操作。
arr是数组名,数组首元素地址,不可以这样操作。
#include<stdio.h> int main() { int arr[10]={0}; int* p=arr; p++; //arr++❌ return 0; }
我们知道通过指针可以访问一个数组的元素,那我们是否写一个代码修改数组的元素和访问呢?
#include<stdio.h> int main() { int arr[10] = { 0 }; int* p = arr; int i = 0; int j = 0; for (i = 1; i < 11; i++) { *p = i; p++; } for (j = 0; j < 10; j++) { printf("%d ", arr[j]); } return 0; }
关于数组和指针的关系,我们已经有了非常清晰的认识。
指针数组
指针数组是指针还是数组?
答案:是数组。是存放指针的数组。
字符数组 —— 存放字符的数组
整型数组 —— 存放整型的数组
指针数组 —— 存放指针(地址)的数组
例如: char* arr[5];//存放字符指针的数组 double* arr2[4];//存放字符指针的数组
我们可以通过指针数组模拟一下二维数组
//使用指针数组,模拟一个二维数组 #include<stdio.h> int main() { int arr1[] = { 1,2,3,4,5 }; int arr2[] = { 2,3,4,5,6 }; int arr3[] = { 3,4,5,6,7 }; //指针数组 int* arr[] = { arr1,arr2,arr3 }; //0 1 2 int i = 0; int j = 0; for (i = 0; i < 3; i++)//找到首元素 { for (j = 0; j < 5; j++)//遍历每一个数组的元素 { printf("%d ", arr[i][j]); } printf("\n"); } return 0; }
✔✔✔✔✔✔✔最后,感谢大家的阅读,有任何错误和不足,欢迎大家指正!!!🙂
代码-----------------→【gitee:https://gitee.com/TSQXG】
联系-----------------→【邮箱:2784139418@qq.com】