C语言之指针的奥秘(三)

一、字符指针变量

在指针的类型中,有字符指针char*,一般使用:

#include<stdio.h>
int main()
{char ch = 'w';char* p = &ch;*p = 'w';return 0;
}

还有一种方式:

#include<stdio.h>
int main()
{const char* p = "hello world";printf("%s\n", p);return 0;
}

 这个代码的本质是把字符串hello world首字符的地址放到p中,即把一个常量字符串的首字符h的地址存放到指针变量p中。

const可去掉,加上const效果更好

 学习一道和字符串相关的题:

#include<stdio.h>
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");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指向的是同一个常量字符串,指向的都是“”hello bit.的地址。C/C++会把常量字符串存储到单独的一个内存区域,当几个指针指向同一个字符串时,他们会指向同一块内存。但是用相同的常量字符串去初始化不同的数组时就会开辟出不同的内存块。所以str1和str2不同,str3和str4相同。

相同的常量字符串没必要保存多份,因为常量字符串不能被修改,所以大家共用一份是能满足需要的,这样也能节省空间!

二、数组指针变量

1.数组指针变量的概念

整型指针变量:存放的是整型变量的地址,能够指向整型数据的指针。

浮点型指针变量:存放的是浮点型变量的地址,能够指向浮点型数据的指针。

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

int *p1[10];
int (*p2)[10];

 p1是指针数组,存放指针的数组;

p2是数组指针,p2先和*结合,说明p2是一个指针变量,然后指针指向的是一个大小为10个整型的数组,所以p2是一个指针,指向数组,叫做数组指针

注意:[ ]的优先级要高于*,所以必须加上( )来保证p先和*结合。

2.数组指针变量初始化

 数组指针类型解析:去掉名字就是,剩下的就是数组指针类型,即int (*)[10] 

三、二维数组传参的本质

若有一个二维数组需要传参给一个函数时,过去会这样写:

#include<stdio.h>
void Print(int arr[3][5], int r, int c)
{int i = 0;for (i = 0; i < r; i++){int j = 0;for (j = 0; j < c; j++){printf("%d ", arr[i][j]);}printf("\n");}
}
int main()
{int arr[3][5] = { {1,2,3,4,5},{2,3,4,5,6},{3,4,5,6,7} };Print(arr, 3, 5);return 0;
}

还有其它写法吗?

二维数组启示可以看作是一维数组的数组,也就是二维数组的每个元素是一个一维数组,那么二维数组的首元素就是第一行,是个一维数组。

根据数组名是数组首元素的地址这个规则,二维数组的数组名就是第一行的地址,是一维数组的地址。由上图可得,第一行的一维数组类型是int [5],所以第一行的地址的类型就是数组指针类型int (*) [5]。

二维数组传参本质上是传递了地址,传递的是第一行这个一维数组的地址。

 若有一个二维数组需要传参给一个函数时,还可以写成指针形式:

#include<stdio.h>
void Print(int(*p)[5], int r, int c)
{int i = 0;for (i = 0; i < r; i++){int j = 0;for (j = 0; j < c; j++){printf("%d ", *(*(p + i) + j));}printf("\n");}
}
int main()
{int arr[3][5] = { {1,2,3,4,5},{2,3,4,5,6},{3,4,5,6,7} };Print(arr, 3, 5);return 0;
}

二维数组传参,形参的部分可以写成数组,也可以写成指针形式。

四、函数指针变量

1.函数指针变量的创建

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

先看一段代码:

我们可以看到运行结果是一样的。我们可以得到:函数是有地址的, 函数名就是函数的地址,也可以通过&函数名的方法获得函数的地址。

如果要将函数的地址存放起来,就要创建函数指针变量:

#include<stdio.h>
int Add(int x, int y)
{return x + y;
}
int main()
{int(*pf1)(int, int) = Add;int(*pf2)(int x, int y) = &Add;return 0;
}

函数指针类型:int  (*)  (int  x,int  y) 

2.函数指针变量的使用

通过函数指针调用函数指针指向的函数。

#include<stdio.h>
int Add(int x, int y)
{return x + y;
}
int main()
{int a = Add(2, 3);printf("%d\n", a);int (*pf)(int, int) = Add;int b = (*pf)(2, 3);printf("%d\n", b);int c = pf(2, 3);printf("%d\n", c);return 0;
}

五、函数指针数组

把函数的地址存到一个数组中,这个数组就叫函数指针数组。

#include<stdio.h>
int Add(int x, int y)
{return x + y;
}
int Sub(int x, int y)
{return x - y;
}
int Mul(int x, int y)
{return x * y;
}
int Div(int x, int y)
{return x / y;
}
int main()
{int(*pfarr[4])(int, int) = { Add,Sub,Mul,Div };//pfarr是函数指针数组int i = 0;for (i = 0; i < 4; i++){int r = pfarr[i](8, 4);printf("%d\n", r);}return 0;
}

函数指针数组:int  (*pfarr[4])(int,int) ——上面代码

函数指针数组类型:int  (*)( ) 

六、转移表

 函数指针的用途:转移表

计算器的一般实现:

#include<stdio.h>
int Add(int x, int y)
{return x + y;
}
int Sub(int x, int y)
{return x - y;
}
int Mul(int x, int y)
{return x * y;
}
int Div(int x, int y)
{return x / y;
}
int main()
{int x = 0;int y = 0;int z = 0;int input = 1;do{printf("*********************\n");printf("**** 1.Add 2.Sub ****\n");printf("**** 3.Mul 4.Div ****\n");printf("**** 0.exit      ****\n");printf("*********************\n");printf("请选择:");scanf("%d", &input);switch (input){case 1:printf("请输入两个数:");scanf("%d %d", &x, &y);z = Add(x, y);printf("%d\n", z);break;case 2:printf("请输入两个数:");scanf("%d %d", &x, &y);z = Sub(x, y);printf("%d\n", z);break;case 3:printf("请输入两个数:");scanf("%d %d", &x, &y);z = Mul(x, y);printf("%d\n", z);break;case 4:printf("请输入两个数:");scanf("%d %d", &x, &y);z = Div(x, y);printf("%d\n", z);break;case 0:printf("退出程序\n");break;default:printf("输入错误\n");break;}} while (input);return 0;
}

使用函数指针数组实现:

#include<stdio.h>
int Add(int x, int y)
{return x + y;
}
int Sub(int x, int y)
{return x - y;
}
int Mul(int x, int y)
{return x * y;
}
int Div(int x, int y)
{return x / y;
}
int main()
{int x = 0;int y = 0;int z = 0;int input = 1;int(*pfarr[5])(int, int) = { 0,Add,Sub,Mul,Div };do{printf("*********************\n");printf("**** 1.Add 2.Sub ****\n");printf("**** 3.Mul 4.Div ****\n");printf("**** 0.exit      ****\n");printf("*********************\n");printf("请选择:");scanf("%d", &input);if (input >= 1 && input <= 4){printf("请输入两个数:");scanf("%d %d", &x, &y);z = pfarr[input](x, y);printf("%d\n", z);}else if (input == 0){printf("退出\n");}else{printf("输入错误\n");}} while (input);return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/pingmian/46329.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

123456

截止2023年10月&#xff0c;目前已公开的官方矢量数据有3个网站&#xff0c;按照公开时间顺序分别是&#xff1a;1&#xff09;全国地理信息资源目录服务系统&#xff1b;2&#xff09;西藏自治区自然资源厅&#xff1b;3&#xff09;福建省标准地图服务。我们将持续更新公开的…

2024较火的软件宣传单页HTML源码

源码介绍 2024较火的软件宣传单页HTML源码&#xff0c;源码由HTMLCSSJS组成&#xff0c;记事本打开源码文件可以进行内容文字之类的修改&#xff0c;双击html文件可以本地运行效果 效果截图 源码获取 2024较火的软件宣传单页HTML源码

自动驾驶可能解决的问题

首先是各种盲区&#xff0c;雷达可能检测到各种东西&#xff0c;而这些是视觉注意不到的 然后是每辆车可以互联互通&#xff0c;整体规划路线

Java二十三种设计模式-单例模式(1/23)

引言 在软件开发中&#xff0c;设计模式是一套被反复使用的、大家公认的、经过分类编目的代码设计经验的总结。单例模式作为其中一种创建型模式&#xff0c;确保一个类只有一个实例&#xff0c;并提供一个全局访问点。本文将深入探讨单例模式的概念、实现方式、使用场景以及潜…

通讯录管理(C++入门练习)

通讯录管理系统 系统需求&#xff1a; 通讯录是一个可以记录亲人、好友信息的工具。本文主要利用C来实现一个通讯录管理系统系统中需要实现的功能如下: 添加联系人:向通讯录中添加新人&#xff0c;信息包括(姓名、性别、年龄、联系电话、家庭住址)最多记录1000人 显示联系…

昇思25天学习打卡营第21天|DCGAN生成漫画头像

DCGAN原理 DCGAN&#xff08;深度卷积对抗生成网络&#xff0c;Deep Convolutional Generative Adversarial Networks&#xff09;是GAN的直接扩展。不同之处在于&#xff0c;DCGAN会分别在判别器和生成器中使用卷积和转置卷积层。 它最早由Radford等人在论文Unsupervised Re…

数据结构历年考研真题对应知识点(哈夫曼树和哈夫曼编码)

目录 5.5.1哈夫曼树和哈夫曼编码 1.哈夫曼树的定义 2.哈夫曼树的构造 【分析哈夫曼树的路径上权值序列的合法性&#xff08;2010&#xff09;】 【哈夫曼树的性质&#xff08;2010、2019&#xff09;】 3.哈夫曼编码 【根据哈夫曼编码对编码序列进行译码&#xff08;201…

【AMBA】AXI总线中的AXLEN、AXSIZE、AXBURST和4K边界

文章目录 AXI传输层级概念AXLEN[7:0]定义突发传输长度AXSIZE[2:0]定义突发传输transfer的位宽AXBURST[1:0]定义突发传输类型4K边界 AXI传输层级概念 在手册的术语表中&#xff0c;与 AXI 传输相关的有三个概念&#xff0c;分别是 transfer(beat)、burst、transaction。用一句话…

树莓派关机

文件 shutdown.sh #!/usr/bin/bash sudo shutdown -r nowpython 文件开头添加 #!/usr/bin/python3

C字符串和内存函数介绍(三)——其他的字符串函数

在#include<string.h>的这个头文件里面&#xff0c;除了前面给大家介绍的两大类——长度固定的字符串函数和长度不固定的字符串函数。还有一些函数以其独特的用途占据一席之地。 今天要给大家介绍的是下面这三个字符串函数&#xff1a;strstr&#xff0c;strtok&#xf…

前端web性能统计

前端web性能统计 1. 背景2. 业界方案2.1 腾讯2.2 蚂蚁金服2.3 字节跳动2.4 美团 3. 相关观念3.1 RAIL模型3.2 性能指标3.3 真实用户监控3.4 performance 4. 性能监控工具介绍5. 推荐采用方案 1. 背景 在如今的数字时代&#xff0c;网站和应用程序的性能对用户体验至关重要。用…

STM32MP135裸机编程:唯一ID(UID)、设备标识号、设备版本

0 资料准备 1.STM32MP13xx参考手册1 唯一ID&#xff08;UID&#xff09;、设备标识号、设备版本 1.1 寄存器说明 &#xff08;1&#xff09;唯一ID 唯一ID可以用于生成USB序列号或者为其它应用所使用&#xff08;例如程序加密&#xff09;。 &#xff08;2&#xff09;设备…

Git代码管理工具 — 3 Git基本操作指令详解

目录 1 获取本地仓库 2 基础操作指令 2.1 基础操作指令框架 2.2 git status查看修改的状态 2.3 git add添加工作区到暂存区 2.4 提交暂存区到本地仓库 2.5 git log查看提交日志 2.6 git reflog查看已经删除的记录 2.7 git reset版本回退 2.8 添加文件至忽略列表 1 获…

0.单片机工作原理

文章目录 最小系统 单片机芯片 时钟电路 复位电路 电源 最小系统 单片机芯片 本次51单片机的芯片为&#xff1a;STC89C52 Flash(闪存)程序存储器&#xff1a;存储程序的空间 SRAM&#xff1a;数据存储器&#xff0c;可用于存放程序执行的中间结果和过程数据 DPTR&#xff1a;…

2024-07-14 Unity插件 Odin Inspector2 —— Essential Attributes

文章目录 1 说明2 重要特性2.1 AssetsOnly / SceneObjectsOnly2.2 CustomValueDrawer2.3 OnValueChanged2.4 DetailedInfoBox2.5 EnableGUI2.6 GUIColor2.7 HideLabel2.8 PropertyOrder2.9 PropertySpace2.10 ReadOnly2.11 Required2.12 RequiredIn&#xff08;*&#xff09;2.…

机器人相关工科专业课程体系

机器人相关工科专业课程体系 前言传统工科专业机械工程自动化/控制工程计算机科学与技术 新兴工科专业智能制造人工智能机器人工程 总结Reference: 前言 机器人工程专业是一个多领域交叉的前沿学科&#xff0c;涉及自然科学、工程技术、社会科学、人文科学等相关学科的理论、方…

Linux编程(三)—makefile快速编译

起因 linux环境下&#xff0c;编译c程序很麻烦&#xff0c;后面g -o demo demo.cpp ……往往跟了许多许多东西&#xff0c;这些每次编译的时候都要书写&#xff0c;所以就产生了makefile快速编译方式&#xff0c;具体操作如下。 怎么用makefile? 第一步&#xff1a;下载 m…

WPF学习(2) -- 样式基础

一、代码 <Window x:Class"学习.MainWindow"xmlns"http://schemas.microsoft.com/winfx/2006/xaml/presentation"xmlns:x"http://schemas.microsoft.com/winfx/2006/xaml"xmlns:d"http://schemas.microsoft.com/expression/blend/2008&…

MySQL 聚簇索引和非聚簇索引有什么区别?

聚簇索引&#xff08;主键索引&#xff09;、非聚簇索引&#xff08;二级索引&#xff09;。 这两者之间的最主要的区别是 B 树的叶子节点存放的内容不同&#xff1a; 聚簇索引的 B 树叶子节点存放的是主键值完整的记录&#xff1b;非聚簇索引的 B 树叶子节点存放的是索引值主…

【面试八股总结】C++内存管理:内存分区、内存泄漏、new和delete、malloc和free

参考资料&#xff1a;代码随想录、阿秀 一、内存分区 &#xff08;1&#xff09;栈区 在执行函数时&#xff0c;函数内部局部变量的存储单元都可以在栈上创建&#xff0c;函数执行结束时这些存储单元自动被释放。栈内存分配运算内置于处理器的指令集中&#xff0c;效率很高&am…