C语言指针进阶-全面分析C指针重难点逐一突破(前篇)

大家好,我是枫晨,几天没更新,手已经开始痒痒了,但是这部分包含的知识点太广泛,我也一直在想方设法找简单易懂例子去讲解这些难点,所以请大家见谅啦,同时在不断调整文章的观感,增加大家阅读体验~

这篇文章全面分析C语言中指针重难点,并分为前后篇幅,如果你是还没有接触过指针的小白,请先看完这篇文章再返回进阶 初阶指针

文章目录

  • 一、字符指针
  • 二、指针数组
  • 三、数组指针
    • 数组名
    • 实战运用

C语言指针进阶-全面分析C指针重难点逐一突破(前篇)_第1张图片

一、字符指针

顾名思义,用来存放字符或者字符串的指针

在指针类型中,我们提到过**char*** 类型,它就是字符指针:

//存放字符的字符指针
char ch = 'w';
char* pc = &ch;

指针pc中存储了变量ch中‘w’字符的地址

char *pch = "abcdef";

对于第一次见到存储字符串的指针,我们首先要进行分析设问:
①**“abcdef”字符串是存储到了指针变量pch中么?(假设是在32位环境下)
分析:在32位环境下,char*类型指针大小才
4字节**,而字符串“abcdef”有六个字节,明显存储不下,所以这个问题解决了。

②那存储的会是字符串的首元素‘a’的地址么?
通过代码来验证:

int main()
{
    char *pch = "abcdef";
    printf("%c\n",*pch);//验证*pch中存储的地址是否是a
    return 0;
}

C语言指针进阶-全面分析C指针重难点逐一突破(前篇)_第2张图片

答案确实如此,指针pch中存储了字符串中首元素的地址‘a’
同时,我们还要了解,“abcdef”是在内存中的常量区创建的,所以又被称为常量字符串,是只读,不可修改的字符串,例如:

int main()
{
    char *pch = "abcdef";
    *pch ='w'
    printf("%c\n",*pch);//验证*pch中存储的地址是否是a
    return 0;
}

此时编译,代码是会报错的C语言指针进阶-全面分析C指针重难点逐一突破(前篇)_第3张图片

所以当我们创建字符指针存放字符串的时候,最好使用const,以表示严谨性和提示他人

const char * pch = “abcdef”;

C语言指针进阶-全面分析C指针重难点逐一突破(前篇)_第4张图片

如果想要打印“abcdef”字符串要如何打印?

//只需要利用%s即可
printf("%s\n",pch);

学习完了字符指针,哪来看一个小练习吧~


判断下列代码的输出结果

int main()
{
	const char* p1 = "abcdef";
	const char* p2 = "abcdef";
	char arr1[] = "abcdef";
	char arr2[] = "abcdef";
	//判断p1和p2关系
	if (p1 == p2)
	{
		printf("p1和p2指针相同\n");
	}
	else
	{
		printf("p1和p2指针不相同\n");
	}
	//判断arr1和arr2关系
	if (arr1 == arr2)
	{
		printf("arr1和arr2指针相同\n");
	}
	else
	{
		printf("arr1和arr2指针不相同\n");
	}
	return 0;
}

答案:image-20220305170109346

为什么呢?答案分析:

C语言指针进阶-全面分析C指针重难点逐一突破(前篇)_第5张图片

C语言指针进阶-全面分析C指针重难点逐一突破(前篇)_第6张图片


二、指针数组

简单回顾:用于存放指针的数组

int a = 10;
int b = 20;
int c = 30;
int *arr[3]={&a,&b,&c};

更加详细的介绍请跳转到指针初阶了解


三、数组指针

数组指针概念:用于存放数组地址指针

创建形式: 类型 (*name)[size]

这里一不小心特别容易写成指针数组,这就是为什么我要在这一篇再一次提起指针数组的原因,它们二者的区别请看图:
C语言指针进阶-全面分析C指针重难点逐一突破(前篇)_第7张图片

数组名

实战先再解决一个问题,概念说数组指针是存放数组地址的,那如何取得数组地址呢?是我们之前文章提及的简简单单用arr代表整个数组的地址么?还是用*&arr?

整一个数组地址

①sizeof(arr)其中的arr代表整一个数组

&arr,可以取出整一个数组的地址

首元素地址

平常中直接写出arr其代表数组中首元素地址

实战运用

int arr[10]={0};
int (*pa)[10]=&arr;
//思考题:
char* ch[5];//怎么样存储这一个数组的地址呢?文末给出答案。

数组指针有什么用?

①一维数组上的应用

//写一个打印函数,利用数组指针打印数组中的内容
int main()
{
    int arr[10]={1,2,3,4,5,6,7,8,9,0};
    int sz = sizeof(arr)/sizeof(arr[0]);//sizeof(arr)//计算整个数组大小
    my_printf(&arr,sz);//&arr,整个数组的地址,为使用数组指针做准备
    return 0;
}
//函数主题部分----本来这部分最好是在main函数前写,为了阅读体验而做出让步
void my_printf(int(*p)[10],int sz)
{
    int i = 0;
    for(i=0;i<sz;i++)
    {
        printf("%d ",*(*p+i));
    }
}

上述代码详解:

C语言指针进阶-全面分析C指针重难点逐一突破(前篇)_第8张图片

但是!这样子运用起来其实特别别扭,我本来直接传arr首元素的地址还更加方便的打印,为何要这么绕来绕去,所以,数组指针一般不应用在一维数组中,反言之,数组指针一般应用在二维数组中。

②数组指针在二维数组中的应用

//写一个打印函数,利用数组指针打印二维数组中的内容
int main()
{
    int arr[3][5]={{1,2,3,,4,5},{2,3,4,5,6},{3,4,5,6,7}}my_printf(arr,3,5);//arr,二维元素里面第一行元素的地址
    return 0;
}
//函数主题部分----本来这部分最好是在main函数前写,为了阅读体验而做出让步
void my_printf(int(*p)[5],int c,intr)//C:行数,r:列数
{
    int i = 0;
	for(i=0;i<3;i++)
    {
        int j = 0;
        for(j=0;j<5;j++)
        {
            printf("%d ",p[i][j]);//或者是*(*(p+i)+j)
		}
        printf("\n");
	}
}

上述代码详解:

C语言指针进阶-全面分析C指针重难点逐一突破(前篇)_第9张图片

C语言指针进阶-全面分析C指针重难点逐一突破(前篇)_第10张图片

C语言指针进阶-全面分析C指针重难点逐一突破(前篇)_第11张图片

对解引用的初步总结

arr[i] == * (arr+i);

arr[i][j] == *(arr+i)[j] == * ( * (arr+i)+j )


总结:

1.字符指针的运用,存放的是字符串的第一个元素的地址

2.数组指针的创建方式是 【数组类型 (*name)[size]】

3.对解引用符号的深入了解

指针还未结束,同志仍需努力!

C语言指针进阶-全面分析C指针重难点逐一突破(前篇)_第12张图片

你可能感兴趣的:(C语言学习教程,C习题专栏,c语言,调试器,visual,studio)