1.字符指针
这是一个简单的字符指针的用法
int main() {char a = 'b';char* p = &a;*p = 'c';return 0;
}
那如果一个字符串赋给指针数组会怎么样呢?
int main() {char* p = "abcdef";return 0;
}
在32位机器下,指针大小为4个字节,那这个指针肯定无法将这个字符串的所有元素地址保存下来
调试起来我们发现p指针实际上存了常量字符串的首元素‘a’的地址
当然,我们也可以打印出来直观的看一下
#include<stdio.h>
int main() {char* p = "abcdef";printf("%c\n", *p);
}
如果你要打印整个字符串,可以这样
#include<stdio.h>
int main() {char* p = "abcdef";printf("%s\n", p);
}
注意:这里的常量字符串“abcdef”
这个字符串是不允许修改的,如果要强行修改,会使程序崩溃
int main() {char* p = "abcdef";*p = 'w';//这里是一个错误的写法
}
我们通常都会在前面加一个const,保证内容无法修改
int main() {const char* p = "abcdef";
}
2.指针数组
本质上就是把数组中原来储存整形,字符,浮点型的元素换成储存地址的元素
int main() {int a = 10;int b = 9;int c = 5;int* arr[3] = {&a,&b,,&c};//存放指针类型的数组——指针数组
}
int main() {int arr1[3] = { 1,2,3 };int arr2[3] = { 2,3,4 };int arr3[3] = { 3,4,5 };int* p[3] = {arr1,arr2,arr3};return 0;
}
再来看一个例子
int main() {int arr1[3] = { 1,2,3 };int arr2[3] = { 2,3,4 };int arr3[3] = { 3,4,5 };int* p[3] = {arr1,arr2,arr3};return 0;
}
这样就模拟了一个二维数组
#include<stdio.h>
int main() {int arr1[3] = { 1,2,3 };int arr2[3] = { 2,3,4 };int arr3[3] = { 3,4,5 };int* p[3] = {arr1,arr2,arr3};int i = 0;for (i = 0;i < 3;i++) {int j = 0;for (j = 0;j < 3;j++) {printf("%d ", p[i][j]);//类似于二维数组的引用方式}printf("\n");}return 0;
}
3.数组指针
数组指针的定义
数组指针是指针
对于整形指针,int* p,是能够指向整形数据的指针
数组指针是:能够指向数组的指针
对比一下指针数组和数组指针:
int* p1[10];//指针数组int(*p2)[10];//数组指针,[10]中的10不可省略
[ ]的优先级高于 *,对于第一个来说 p1先与[ ]结合
而第2个加上了括号,*先与p2结合
注意:数组指针int (*p)[10]中的[10]表明该指针指向的数组是有十个元素的数组,而不是该指针存了数组中十个元素的地址
我们看这样的代码
#include<stdio.h>
int main() {int arr[10] = { 0 };printf("%p\n", arr); //类型:int*printf("%p\n", arr + 1);printf("%p\n", &arr[0]); //类型:int*printf("%p\n", &arr[0] + 1);//&arr是取出整个数组的地址printf("%p\n", &arr);//类型:int(*)[10]printf("%p\n", &arr + 1);//+1直接跳过整个数组的大小}
那对于这样的&arr,我们应该如何储存?
int* p1 = &arr;//错误,原因是类型不同,int(*p)[10]无法转化到int*int(*p)[10] = &arr;//正确
我们就用数组指针
这里&arr的类型是int (*)[10]
我们通过这个例子,运用一下数组指针
void print1(int* arr, int sz) {int i = 0;for (i = 0;i < sz;i++) {printf("%d ", *(arr + i));}
}
int main() {//依次打印数组中的元素int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };int sz = sizeof(arr) / sizeof(arr[0]);print1(arr, sz);return 0;
}
运用数组指针
void print1(int(*p)[10], int sz) {int i = 0;for (i = 0;i < sz;i++) {//*p=*(&arr)=arr,*与&相抵消,所以*p相当于数组名,数组名是首元素地址,所以*p就是&arr[0]printf("%d ", *(*p + i));}
}
int main() {int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };int sz = sizeof(arr) / sizeof(arr[0]);print1(&arr, sz);return 0;
}
这种写法复杂,不推荐,仅用于例子
我们再来看一个二维数组的例子
#include<stdio.h>
void print1(int arr[3][5], int c, int r) {//打印二维数组int i = 0;for (i = 0;i < 3;i++) {int j = 0;for (j = 0;j < 5;j++) {printf("%d ", arr[i][j]);}printf("\n");}
}
int main() {int arr[3][5] = { {1,2,3,4,5},{2,3,4,5,6},{3,4,5,6,7} };print1(arr, 3, 5);
}
用数组指针可以这样
void print1(int (*p)[5], int c, int r) {int i = 0;for (i = 0;i < c;i++) {int j = 0;for (j = 0;j < r;j++) {//*(p+i)拿到第i行的数组名,也就是拿到第i行第一个元素的地址printf("%d ", *(*(p + i)+j));//也可写成p[i][j]}printf("\n");}
}
int main() {int arr[3][5] = { {1,2,3,4,5},{2,3,4,5,6},{3,4,5,6,7} };print1(arr, 3, 5);
}
*(*(p+i)+j)是p[ i ] [ j ]更本质的表现
当传参是数组指针时
arr[ i ] = *(*arr+i)
arr[ i ][ j ] = *(arr+i)[ j ] = *(*(arr+i)+j)
通常解两次引用可获取到元素,第一次解引用,是抵消&,得到数组名,第二次是得到数组名(地址)中的元素