目录
一、改变常量字符串,是否会导致出错?
二、指针数组:
三、数组指针:
四、数组指针与二级指针的区分:
五、二维数组传参及数组指针的应用:
六、辨认指针和数组:
//代码1:
int main()
{
char ch = 'w';
char* pc = &ch;//pc是指向一个字符串指针变量
char* p = "hello bit";
//"hello bit"是一个常量字符串 - 存放在内存的常量区,是不允许更改的,更改就会导致err
//上面表达式的作用是:把常量字符串"hello bit"的第一个字符h的地址赋值给p
printf("%c\n",*p);//可以看出指针p存放的是字符h的地址
printf("%s\n",p);//因为字符串是连续存放的,通过首地址可以打印'\0'之前的字符串
return 0;
}
一、改变常量字符串,是否会导致出错?
因为常量字符串是放在常量区的,不允许更改的,更改就会导致如下错误。
解决方案:
所以为了不允许更改常量字符串,所以可以在指针p前面用const 修饰,避免错误发生
//代码2:
int main()
{
char str1[] = "hello bit.";
char str2[] = "hello bit.";
const char* str3 = "hello bit.";//指针指向的是常量字符串
const char* str4 = "hello bit.";
if (str1 == str2)//比较的是俩个数组的首元素的地址
printf("str1 and str2 are same\n");//数组创建开辟的是俩块独立的空间
else
printf("str1 and str2 are not same\n");//YES
//"hello bit"是一个常量字符串,放在常量区,不允许修改,因为是同一个常量字符串,并且不允许修改,所以
//没有必要创建俩个空间,所以str3,str4,指向的是同一个起始空间地址
if (str3 == str4)
printf("str3 and str4 are same\n");//YES
else
printf("str3 and str4 are not same\n");
return 0;
}
图解:
代码3:
//指针数组 - 存放的指针的数组
//int arr[10];//整形数组 - 存放整形的数组
//char arr[5];//字符数组 - 存放字符的数组
int main()
{
char* arr[5];//arr是存放字符指针的数组
int* arr2[4];//arr2是存放整形指针的数组
return 0;
}
如果想将数组中的每个元素打印将如何?
比如:只需要找到 (arr2[0]) --- arr2下标为0的地址,找到a的地址 --&a,然后对a的地址解引用即可
parr里面存放的是arr1,arr2,arr3三个一维数组,三个一维数组里面存放的又是各自的5个数。
//p[i] (指针p中下标为i的元素) == *(p+i) //parr[i][j] == *(parr[i] + j)
//代码4:
int main()
{
const char* arr[5] = {"abcdef","cdefr","acscds","asdfds","sacddfr"};
//指针指向的字符串是常量字符串,不允许更改,所以加const
int i = 0;
//字符串的打印
for (i = 0;i < 5;i++)
{
printf("%s\n ",arr[i]);
}
return 0;
}
//一级指针地址用二级指针存放,或者说,二级指针存放一级指针的地址,指向一级指针
int* arr[5];//指针数组
//arr 是数组名,数组名是数组首元素的地址,首元素的类型是int*
int** p = arr;//&(arr[0])
int** p2 = &arr[3];
图解:
//代码5:
//整形指针 int* p -- 指向整形的指针
//字符指针 char* p -- 指向字符的指针
//数组指针 --- 指向数组的指针--是一个指针
int main()
{
int a = 10;
int *p1 = &a;//整形的地址存放在整形指针中
//p1的类型是int*
char ch = 'w';
char * p2 = &ch;//字符的地址存放在字符指针中
//p2的类型是char*
int arr[10] = {0};
int (*p3)[10] = &arr;//数组的地址存放在数组指针中
//*p3表示p3是一个指针,[10]表示p3指向一个数组,数组一共有10个元素,每个元素的类型int
//数组指针p3的类型是int(*)[10]
//总结:去掉名字剩下的就是类型
int arr[10] = {0};
int *p = arr;//数组首元素地址
return 0;
}
上面说数组名是首元素地址这句话还是是有些问题的,还有俩个例外:
//代码6:
int main()
{
//数组的地址用数组指针来接收
int* arr[10];
int* (*p)[10]= &arr;//&arr表示整个数组的地址,数组的地址应该用数组指针接收
//*p表示p是一个指针,指向一个数组,数组中有10个元素,每个元素是int* 类型
//二级指针是用来存放一级指针地址的
int* arr1[10];
int* *p2 = arr1;//arr1表示的是首元素地址,而首元素是int*,所以arr1表示的是int* 类型的地址,所以用二级指针接收
//*p2表示的是p2是一个指针,指向的元素是int* 类型
}
传过去的是整个数组的地址怎么打印这个数组中的元素呢?
//代码7:
void print1(int (*parr)[10] ,int sz)//数组指针接收,*parr表示parr是一个指针,指向的数组元素有10个,每个都是int 类型
{
int i = 0;
for (i = 0;i < sz;i++)
{
printf("%d",parr[i]);//parr[i] == *(parr+i) -- 而parr是整个数组的地址,+1跳过的是一个数组的大小,err
}
}
void print2(int (*parr)[10],int sz)//(*parr) 相当于parr指向的数组的数组名
{
int i = 0;
for (i = 0; i < sz; i++)
{
printf("%d ",(*(parr))[i]);//数组指针:里面存放的是数组的地址,*(数组指针) == 数组
printf("%d ",parr[0][i]);//数组指针parr里面存放的是数组的地址,parr看作一个二维数组,那么先找到parr下标为0的,也就是arr数组,也就是第一行的元素,40个字节
printf("%d ",*(parr + 0)[i]);//parr里面存放的是数组arr的地址,*parr找到的就是arr数组
}
}
int main()
{
int arr[] = {1,2,3,4,5,6,7,8,9,10};
int sz = sizeof(arr) / sizeof(arr[0]);
/*print1(&arr,sz);*///传过去的是整个数组的地址, 这是一个错误的示范
print2(&arr, sz);
}
//代码8:
void print1(int arr[3][3],int a ,int b)//二维数组传参,传过来是第一行的地址,就是这个指针下标为0的一维数组
{
//打印二维数组
int i = 0;
int j = 0;
for (i = 0;i < a;i++)
{
for (j = 0;j < b;j++)
{
/*printf("%d ",*(*(arr + i) + j));*/
printf("%d ",arr[i][j]);// p[i] = *(p + i)
}
printf("\n");
}
}
//数组指针
void print2(int (*p)[3],int a,int b)//传过来的是第一行的地址,所以数组指针指标是第一行,一维数组中有三个元素,所以[3]
{
int i = 0;
int j = 0;
for (i = 0;i < a;i++)
{
for (j = 0;j < b;j++)
{
/*printf("%d ",*(*(p + i) + j));*/
printf("%d ",p[i][j]);
}
printf("\n");
}
}
int main()
{
int arr[3][3] = {1,2,3, 3,4,5, 6,7,8};
//二维数组传参
/*print1(arr, 3, 3);*/
print2(arr,3,3);//arr 是数组名,数组名是首元素地址,首元素为第一行的地址
return 0;
}
六、辨认指针和数组:
int arr[5];//整形数组
int* parr1[10];//parr1是一个数组,10个元素,每个元素是int* 的,所以是一个存放指针的数组
int(*parr2)[10];//parr2是一个数组指针,该指针指向的数组有10个元素,每个元素是int的
int(*parrr3[10])[5];//parr3是一个数组,数组有10个元素
//每个元素是一个数组指针,该指针指向的数组有5个元素,每个元素是int
本文为指针部分的知识点整理,如有错误,还请大家评论区多多评论