【蒸滴C】C语言指针进阶详解
目录
一、字符指针
(1)开篇小菜
(2)面试题
解析
二、数组指针
&数组名和数组名
三、函数指针
四、函数指针数组
函数指针数组的定义
大家好,欢迎来到【蒸滴C】详解系列,本期博客我整理了C语言中指针的进阶知识,希望能对大家有所帮助
本篇博客的在内容上为上一篇【蒸滴C】系列中指针入门知识的承接,为了知识的连贯,还没看过的小伙伴请先移步这篇文章:
【蒸滴C】C语言指针入门很难?看这一篇就够了_追梦小蔡的博客-CSDN博客刚入门C语言的小白或多或少被指针这块内容折磨过,我自己在学校听老师讲课也是一脸模糊的样子。不过我那时候不断提醒自己,这块内容这块内容对于初学者来说是会有点难度,我现在刚开始接触,自然会很难,但重要的是要坚持下去,并愿意从差开始。而经过了一个寒假的学习,我对指针这块内容有了比较深的理解,看完这篇博客保证你对指针的理解会更深一步!https://blog.csdn.net/C_Small_Cai/article/details/129041030?spm=1001.2014.3001.5502
一、字符指针
在指针入门的时候我们已经知道了指针类型中有一种字符指针类型: char* ,在这里就用一道简单的例题,引出下文吧~
(1)开篇小菜
题目要求:这里是把一个字符串放到 ps 指针变量里了吗?
#include<stdio.h>int main()
{char* ps = "hello world";printf("%s", ps);return;
}
运行结果如下:
由此可见,本质上是把字符串 hello world 首字符的地址放到了 ps 中
也就是把 常量字符串的首字符 h 的地址放到 指针变量 ps 中
(2)面试题
那接着我们再来看一道面试题:
请大家思考一下输出结果是什么
#include <stdio.h>
int main()
{char str1[] = "hello world.";char str2[] = "hello world.";const char* str3 = "hello world.";const char* str4 = "hello world.";if (str1 == str2)printf("str1 and str2 are same\\n");elseprintf("str1 and str2 are not same\\n");if (str3 == str4)printf("str3 and str4 are same\\n");elseprintf("str3 and str4 are not same\\n");return 0;
}
这里最终输出是:
解析
这里str3和str4指向的是一个同一个常量字符串。C/C++会把常量字符串存储到单独的一个内存区域,当几个指针。
指向同一个字符串的时候,他们实际会指向同一块内存。但是用相同的常量字符串去初始化不同的数组的时候就会开辟出不同的内存块。所以str1和str2不同,str3和str4不同。
二、数组指针
在数组指针这部分,我们先来聊聊 &数组名和数组名
&数组名和数组名
我们知道arr是数组名,数组名表示数组首元素的地址。
那&arr数组名到底是啥?
我们先看一段代码
#include <stdio.h>
int main()
{int arr[10] = {0};printf("%p\\n", arr);printf("%p\\n", &arr);return 0;
}
其运行结果如图:
诶!这时候有一部分长得比较帅的小伙伴就会说了:“数组名和&数组名打印的地址是一样的,所以他俩没有区别!”
害,先别着急,是驴子是马还得出来溜溜才知道呢,我们再看:
#include <stdio.h>
int main()
{int arr[10] = { 0 };printf("arr = %p\\n", arr);printf("&arr= %p\\n", &arr);printf("arr+1 = %p\\n", arr + 1);printf("&arr+1= %p\\n", &arr + 1);return 0;
}
运行结果:
通过上边这个代码我们可以看出:
其实&arr和arr,虽然值是一样的,但是意义应该不一样的。
实际上: &arr 表示的是数组的地址,而不是数组首元素的地址。(整个数组的地址)
本例中 &arr 的类型是: int(*)[10] ,是一种数组指针类型
数组的地址+1,跳过整个数组的大小,所以 &arr+1 相对于 &arr 的差值是40.
三、函数指针
还是先来看看一段代码:
#include <stdio.h>
void test()
{printf("hehe\\n");
}int main()
{printf("%p\\n", test);printf("%p\\n", &test);return 0;
}
结果:
输出的是两个地址,这两个地址是 test 函数的地址。
那我们的函数的地址要想保存起来,怎么保存?
我们再看代码:
下面pfun1和pfun2哪个有能力存放test函数的地址?
void test()
{printf("Hello CSDN\\n");
}void (*pfun1)();
void* pfun2();
首先,能给存储地址,就要求pfun1或者pfun2是指针,那哪个是指针?
答案是:
pfun1可以存放。pfun1先和*结合,说明pfun1是指针,指针指向的是一个函数,指向的函数无参
数,返回值类型为void。
四、函数指针数组
越来越玄乎了是吧?刚开始接触的我也是很懵,不过好在后面咬牙啃下去了,大家在学习中遇到
困难的时候,才是最锻炼自己能力的时候。想想看,这个过程中去查找资料,不是会学到更多吗?
好了闲话少叙,下面进入正题:
函数指针数组的定义
把函数的地址存到一个数组中,那这个数组就叫函数指针数组
来看函数指针数组如何书写:
int (*pa[10])();
pa 先和 [ ] 结合,说明 pa 是数组,那么数组的内容是什么呢?
其实就是 int (*)() 类型的函数指针。
但是关于函数指针数组的用途,在这里就先不详细展开了,但他最常用的地方就是: 转移表 。日后我会在更新一篇转移标的博客详细描写
本来这部分内容也是很多的,但我删去了一些不太常见的内容,剩下的基本算是入行以后会用到的了,对大学生来说已经是进阶的知识了。好了,指针进阶就到讲到这里吧