【C语言】指针篇-一篇搞定不同类型指针变量-必读指南(3/5)

这篇具有很好参考价值的文章主要介绍了【C语言】指针篇-一篇搞定不同类型指针变量-必读指南(3/5)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

					  男儿不展风云志,空负天生八尺躯。——《警世通言·卷四十》

【C语言】指针篇-一篇搞定不同类型指针变量-必读指南(3/5),C语言,c语言,开发语言,学习,c++

🌈个人主页:是店小二呀
🌈C语言笔记专栏:C语言笔记
🌈C++笔记专栏: C++笔记

🌈喜欢的诗句:无人扶我青云志 我自踏雪至山巅
【C语言】指针篇-一篇搞定不同类型指针变量-必读指南(3/5),C语言,c语言,开发语言,学习,c++
上篇回顾:上篇我们通过数组名为切入口引出数组与指针间的关系,本篇将介绍不同类型的指针变量在不同场景中的使用


【C语言】指针篇-一篇搞定不同类型指针变量-必读指南(3/5),C语言,c语言,开发语言,学习,c++

字符指针变量

对于字符和字符串,C语言统一使用char类型来表达式。对此字符指针变量有两种表示方法:

  1. 第一种: char ch='a'; char *p=&ch;
  2. 第二种: const char *pstr="Hellow world";

问题:关于const char *pstr="Hellow world"是将整个字符串放到字符指针里面了吗?

解释:本质是字符串"Hellow world"首字符(H)的地址放到字符指针变量pstr中.

面试题<剑指offer>

int main()
{
char str1[] = "hellow world";
char str2[] = "hellow world";
const char *str3 = "hellow world";
const char *str4 = "hellow world";
if(str1 ==str2)
        printf("str1 and str2 are same\n");
    else
    	printf("str1 and str2 are not same\n");	
if(str3 ==str4)
        printf("str3 and str4 are same\n");
    else	
        printf("str3 and str4 are not same\n");
return 0;
}
结果:
str1 and str2 are not same 
str3 and str4 are same

解释:

str3str4指向的是一个同一个常量字符串。C/C++会把常量字符串储存到单独的一个内存区域(常量区),当多个指针指向同一个字符串时,实际是指向同一块内存。但是用相同的常量字符串去初始化不同的数组的时就会开辟不同的内存块,更直白说就算将常量字符串从常量区拷贝一份到数组中,那么在数组初始化时就会在栈中开辟不同的内存块。

使用指针初始化的"hello world"是一个常量字符串,str3指向首字符地址,但该地址在于进程的text段,text段可以保存常量还可以执行代码,是不允许可写权限,只有可读、可执行权限(了解即可)

char *p="hellow";
p[1]='d';//*(p+1)='d';//出现段错误

数组指针变量(指针数组,这里需要注意偏正)

  • 整形指针变量:int *p(存放的是整形变量的地址,能够指向整形数据的指针)
  • 字符指针变量char *p(存放的是字符或字符串首元素的地址,能够指向字符或者字符串数据的指针)

依次类推

数组指针变量:存放的是数组的地址,能够指向数组的指针变量

那个是数组指针变量?那个是指针数组变量?
int *p1[10];
int (*p2)[10];

:[]的优先级高于*。

  • p1和[]结合形成一个数组,指向数组中int *类型的元素,是指针数组。

  • p2和 *加上了()保证了p2先和 *结合形成一个指针,指向一个大小为10个整形的数组指向一个多大的数组),是数组指针(存放的是数组的地址)

数组指针的初始化

int (*p) [10] = &arr;
|     |    |
|     |    |
|     |    []:p指向数组的元素个数
|     p:数组指针变量名
int:p指向的数组的元素类型

二维数组传参的本质

【C语言】指针篇-一篇搞定不同类型指针变量-必读指南(3/5),C语言,c语言,开发语言,学习,c++

二维数组是由多个一维数组组成的,也是连续存放数据。这样说明:二维数组的每个元素都是一个一维数组,根据数组名是数组首元素的地址这个规则,二维数组的数组名表示是第一行的地址(一维数组的地址)

对此第一行的地址的类型是数组指针类型int(*)[5]。意味着跟一维数组传参本质一样,也是传递地址,传递的是第一行这个一维数组的地址

小总结:二维数组传参,形参的部分可以采用数组或者指针形式

void test1(int nums[][5]);//数组类型
void test2(int (*nums)[5]);//指针类型
int main()
{
    int nums[][5]={{1,2,3,4,5},{2,3,4,5,6},{3,4,5,6,7}};
    test1(nums);
    test2(nums);
    return 0;
}

函数指针变量

函数指针变量:存放函数地址的,通过函数的地址来调用函数

问题:那么如何得到函数的地址呢?

void test();
int main()
{
    printf("&test==%p",&test());
    printf("test==%p",test());
    return 0;
}
结果:
&test==00991253
test==00991253

通过输出的结果:函数是有地址的,函数名就是函数的地址,&函数名的方式也可以获得函数的地址

void (*pf1)() = &test;
void (*pf2)() = test;

函数指针变量初始化

int    (*pf3)        (int x, int y)
 |        |           ------------
 |        |                 |
 |        |     pf3指向函数的参数类型和个数的交代
 |    函数指针变量名
 pf3指向函数的返回类型
    
int (*) (int x, int y) //pf3函数指针变量的类型

函数指针变量的使用(通过函数指针调用指针指向的函数)

int Add(int x,int y)
{
	return x+y;
}
int main()
{

    int (*p)(int x,int y)=Add;//如果需要存放多个函数地址,需要使用到函数指针数组
    printf("%d\n",(*p)(a,b));
    printf("%d\n",p(a,b));
    return 0;
}

说明:p(a,b)(*p)(a,b)效果是相同的,因为函数名本身就是函数指针变量


函数指针数组

如果我们需要把多个函数的地址存在数组中,函数名是一个函数指针变量,就需要利用到指针数组和函数配合了

存放函数的地址的指针数组

int (*)()(类型的函数指针):
void (*p[3])(void x,void y)={Add,Sub};

方便理解:
p[] = x;
void (*x)(void x,void y)={Add,Sub};

说明:p先和[]结合,说明p是数组,数组的内容void (*)()类型的函数指针。


转移表

函数指针数组的用途:转移表

比如:使用函数指针数组实现计算器

实现函数功能

int add(int a, int b)
{
	return a + b;
}
int sub(int a, int b)
{
	return a - b;
}
int mul(int a, int b)
{
	return a * b;
}
int div(int a, int b)
{
	return a / b;
}
int main()
{
	int x = 0, y = 0;//操作数
	int input = 0;//选择功能
	//前面加个0,方便输入数字得到相对函数功能
	int (*computer[5])(int x,int y) = {0,add,sub,mul,div };
	do
	{
		mune();
		scanf("%d", &input);
		if (0 < input && input <= 4)
		{
			printf("输入两个操作数\n");
			scanf("%d %d", &x, &y);
			int ret = (*computer[input])(x, y);
			printf("结果为%d\n", ret);
		}
		else if (input == 0)
		{
			printf("退出计算机\n");
		}
		else
		{
			printf("非法输入\n");
		}
	} while (input);
	return 0;
}

说明:根据函数指针数组的结构,我们可以通过两个部分,选择数组中函数,并且为调用函数选择函数参数。

缺点:这么好用的东西也有他自己的美中不足,不知道你有没有发现,这些函数的功能的参数部分,返回值类型是一样的,如果需要使用函数指针算组,建议需要实现的函数参数部分和返回值类型保持一致。


typedef 关键字

typedef:用于类型重命名的(将复杂的类型进行简单化)(typedef是定义了一种类型的新别名,不同于宏,它不是简单的字符串替换)

语法:typedef 类型(自定义取名)

例子:

typedef int it;
typedef int *  intt;
对于数组指针和函数指针有一些区别
typedef int(*part)[5];//数组指针类型int (*)[5]
typedef int (*part)(int;)//函数指针类型 int (*)(int);

关于typedef相关的知识点,这里只是简单介绍。比如:在使用typedef遇到const对象就可能会出现问题如果大家对typedef这个知识点感兴趣,可以参考这份资料:typedf

这里就简单分享一个typedef遇到const的陷阱

typedef char* Ptr
int compare(const Ptr e1 , const Rtr e2)

说明:typedef它不是简单的字符串替换,先分析const Ptr意味着Ptr整体被const赋予了常量性,那么typedef以后应该是char * const e1保证Ptr指针本身的常量性、不能修改指针本身。


【C语言】指针篇-一篇搞定不同类型指针变量-必读指南(3/5),C语言,c语言,开发语言,学习,c++

谢谢大家的观看,这里是个人笔记,希望对你学习C有帮助。文章来源地址https://www.toymoban.com/news/detail-857591.html

到了这里,关于【C语言】指针篇-一篇搞定不同类型指针变量-必读指南(3/5)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包赞助服务器费用

相关文章

  • 【JAVA】数据类型与变量(主要学习与c语言不同之处)

    【JAVA】数据类型与变量(主要学习与c语言不同之处)

    ✅作者简介:大家好,我是橘橙黄又青,一个想要与大家共同进步的男人😉😉 🍎个人主页:橘橙黄又青-CSDN博客 目标: 1. 字面常量 2. 数据类型 3. 变量 在上节课 HelloWorld 程序中, System.Out.println(\\\"Hello World\\\") ; 语句,不论程序何时运行,输出的都是 Hello World,其实 \\\"Hello Wo

    2024年03月28日
    浏览(8)
  • Go语言变量使用指南:声明、类型转换与字符串操作

    Go语言变量使用指南:声明、类型转换与字符串操作

    深入了解Go语言中变量的声明方式、字符和布尔类型的细节、字符串的不可变性以及基本数据类型之间的转换规则。

    2024年02月10日
    浏览(32)
  • 一篇搞定C语言操作符(详解含示例)

    一篇搞定C语言操作符(详解含示例)

    目录 一.操作符是什么? 基本特征 语义 优先级 结合性 二.操作符的分类 三.操作符各类详解 1.算数操作符(+     -     *     /     %) (1)优先级: (2)除法操作符(/)的计算规则及注意事项 (3)取余操作符(%)的计算规则 (4)算术操作符示例代码 2.移位操作符

    2024年02月10日
    浏览(10)
  • 《C和指针》笔记12: 存储类型(自动变量、静态变量和寄存器变量)

    《C和指针》笔记12: 存储类型(自动变量、静态变量和寄存器变量)

    在 代码块内部声明的变量 的缺省存储类型是自动的(automatic),也就是说它存储于堆栈中,称为自动(auto)变量 。auto就是用于修饰这种存储类型的,但它极少使用,因为代码块中的变量在缺省情况下就是自动变量。 在程序执行到声明自动变量的代码块时,自动变量才被创

    2024年02月10日
    浏览(12)
  • 【C语言】-- 一篇带你了解指针,内存,解引用

    【C语言】-- 一篇带你了解指针,内存,解引用

    目录 1、什么是指针? 1.1 内存 1.2 指针变量 二、指针和指针类型 1、指针类型 2、指针+整数 3、指针的解引用 三、野指针 1、野指针成因 (1) 指针未初始化 (2) 指针越界访问 (3) 指针指向的空间释放 2、如何规避野指针 四、指针运算 1、指针-指针        本篇文章我们来了解C语

    2024年02月16日
    浏览(17)
  • 【C语言】 指针的进阶 看这一篇就够了

    【C语言】 指针的进阶 看这一篇就够了

    目录 1.字符指针 2.数组指针 3.指针数组 4.数组传参和指针传参 5.函数指针 6.函数指针数组 7.指向函数指针数组的指针 8.回调函数 9.qsort排序和冒泡排序 让我们一起来回顾一下指针的概念! 1.指针就是一个变量,用来存放地址,地址唯一标识一块内存空间。 2.指针的大小是固定

    2023年04月22日
    浏览(11)
  • 【C语言】——指针四:字符指针与函数指针变量

    【C语言】——指针四:字符指针与函数指针变量

      在前面的学习中,我们知道有一种指针类型为 字符指针: c h a r ∗ char* c ha r ∗ 。下面我们来介绍它的使用方法。    使用方法:      如果我们想 存储字符串 ,可以用什么方法呢?之前我们一般都是用 字符数组 ,那还有什么办法呢?其实, 字符指针 也是可以

    2024年04月12日
    浏览(27)
  • C语言指针操作(二)指针变量作为函数参数

    C语言指针操作(二)指针变量作为函数参数

    指针变量作为函数参数详解,形参和实参之间的值传递如何传递?如何改变指针变量所指向的变量? 函数的参数不仅可以是整型,浮点型,字符型等数据,还可以是指针类型;它的作用是将一个变量的地址传送到另一个函数中。 关于地址,指针,指针变量可以参考一下这篇

    2024年02月04日
    浏览(15)
  • c语言---函数指针变量

    c语言---函数指针变量

    函数指针变量应该是用来存放函数地址的,未来通过地址能够调用函数的。 那么函数是否有地址呢? 接下来看看: 运行结果: 确实打印出来了地址,所以函数是有地址的,函数名就是函数的地址,当然也可以通过 函数名 的方式获得函数的地址。这两个结果一模一样。 如果

    2024年02月22日
    浏览(13)
  • 【C语言】const修饰普通变量和指针

    【C语言】const修饰普通变量和指针

    大家好,我是苏貝,本篇博客带大家了解const修饰普通变量和指针,如果你觉得我写的还不错的话,可以给我一个赞👍吗,感谢❤️ 用const修饰普通变量时,是在语法层面限制了变量的修改,但是本质上,变量还是变量,是一种不能被修改的变量。以下两种定义方式都可以:

    2024年02月12日
    浏览(9)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包