C语言进阶 - 指针1 - 知识点整理

目录

一、改变常量字符串,是否会导致出错?

 二、指针数组:

 三、数组指针:

 四、数组指针与二级指针的区分:

 五、二维数组传参及数组指针的应用:

六、辨认指针和数组:


//代码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;
}



一、改变常量字符串,是否会导致出错?

因为常量字符串是放在常量区的,不允许更改的,更改就会导致如下错误。

C语言进阶 - 指针1 - 知识点整理_第1张图片

解决方案:

所以为了不允许更改常量字符串,所以可以在指针p前面用const 修饰,避免错误发生

C语言进阶 - 指针1 - 知识点整理_第2张图片

//代码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;
}

图解:

C语言进阶 - 指针1 - 知识点整理_第3张图片C语言进阶 - 指针1 - 知识点整理_第4张图片

 二、指针数组:

代码3:
//指针数组 - 存放的指针的数组

//int arr[10];//整形数组 - 存放整形的数组
//char arr[5];//字符数组 - 存放字符的数组

int main()
{
	char* arr[5];//arr是存放字符指针的数组
	int* arr2[4];//arr2是存放整形指针的数组
	return 0;
}

C语言进阶 - 指针1 - 知识点整理_第5张图片

 如果想将数组中的每个元素打印将如何?

比如:只需要找到 (arr2[0])   --- arr2下标为0的地址,找到a的地址 --&a,然后对a的地址解引用即可

C语言进阶 - 指针1 - 知识点整理_第6张图片

 C语言进阶 - 指针1 - 知识点整理_第7张图片

 parr里面存放的是arr1,arr2,arr3三个一维数组,三个一维数组里面存放的又是各自的5个数。

 如何打印arr1,arr2,arr3数组里面的元素?C语言进阶 - 指针1 - 知识点整理_第8张图片

       

  //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];

 图解:

 C语言进阶 - 指针1 - 知识点整理_第9张图片C语言进阶 - 指针1 - 知识点整理_第10张图片

 三、数组指针:

//代码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;
}

 C语言进阶 - 指针1 - 知识点整理_第11张图片

 上面说数组名是首元素地址这句话还是是有些问题的,还有俩个例外:

C语言进阶 - 指针1 - 知识点整理_第12张图片

 四、数组指针与二级指针的区分:

//代码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

C语言进阶 - 指针1 - 知识点整理_第13张图片

本文为指针部分的知识点整理,如有错误,还请大家评论区多多评论

你可能感兴趣的:(【C语言学习】,c语言,开发语言,后端)