指针系列三

文章目录

  • 1.字符指针:
  • 2.数组指针:
  • 3.二维数组传参的本质
  • 4.函数指针变量
    • typedef 关键字
  • 5.函数指针数组
  • 6.转移表

在这里插入图片描述

1.字符指针:

字符指针,也称为字符串指针,是指向内存中的字符或字符串的指针。
在C语言中,字符串被表示为以空字符 '\0' 结尾的字符数组。

#include <stdio.h>int main() 
{// 字符指针的声明和初始化char *str = "Hello, bit!";// 使用字符指针打印字符串printf("字符串: %s\n", str);// 使用指针算术运算访问单个字符printf("第一个字符: %c\n", *str);printf("第二个字符: %c\n", *(str + 1));return 0;
}

解释:

  • 我们声明一个字符指针 str 并将其初始化为字符串 "Hello, bit!"。本质是把字符串hello world的首地址放到了str中。
  • 然后使用 %s 格式说明符打印整个字符串。
  • 使用指针算术运算,我们访问并打印字符串的单个字符。
    在这里插入图片描述
    来看一道字符串相关的笔试题 ——from《剑指offer》
#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;
}

在这里插入图片描述

2.数组指针:

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

int *p1[10];
//p是一个指针变量数组(数组的元素类型都是指针),指针指向整型数组
int (*p2)[10];
//p是一个指针变量,然后指向的是大小为10的整型数组
//(数组元素10个,每个元素类型是int)

[]的优先级是要高于*的,所以必须加上( )来保证p*先结合
在这里插入图片描述

#include <stdio.h>int main() 
{// 声明并初始化整型数组int arr[] = {1, 2, 3, 4, 5};// 声明一个数组指针int *ptr;// 使用数组的基地址初始化数组指针ptr = arr;// 使用数组指针访问数组元素printf("数组元素: ");for (int i = 0; i < 5; i++){printf("%d ", *(ptr + i));}printf("\n");return 0;
}

运行结果
在这里插入图片描述

#include <stdio.h>int main()
{// 声明并初始化整型数组int arr[5] = { 1, 2, 3, 4, 5 };// 声明一个数组指针int (*ptr)[5]=&arr;//得到的是数组地址return 0;
}

在这里插入图片描述

在这里插入图片描述

解释:

  • 我们声明一个整型数组 arr 并将其初始化为一些值。
  • 我们声明一个数组指针 ptr
  • 使用数组 arr 的基地址初始化数组指针 ptr
  • 使用指针算术,我们访问并打印数组的元素。

字符指针和数组指针的区别:

  1. 数据类型:

    • 字符指针(char *)用于指向字符或字符串。
    • 数组指针(int *float *等)用于指向数组的第一个元素。
  2. 用途:

    • 字符指针通常用于字符串的操作和处理。
    • 数组指针用于高效访问数组的元素。

3.二维数组传参的本质

先看不用指针怎么实现二维数组的传参

#include <stdio.h>
void test(int a[3][5], int r, int c)
{int i = 0;int j = 0;for (i = 0; i < r; i++){for (j = 0; j < c;j++){printf("%d " , a[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} };test(arr, 3, 5);return 0;
}

在这里插入图片描述
这里实参是二维数组,形参也可以写出二维数组
那么用指针怎么写捏
首先我们要明确,二维数组名表示的是第一行的地址
我们可以知道一维数组的类型是int[5],所以第一行第地址数组类型就是int(*)[5]
那就意味着二维数组传参的本质是传递了地址,传递的是这个一维数组的地址

所以我们可以这么写

#include <stdio.h>
void test(int *p [5], int r, int c)
{int i = 0;int j = 0;for (i = 0; i < r; i++){for (j = 0; j < c;j++){printf("%d " , *(*(p+i)+j));//*(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} };test(arr, 3, 5);return 0;
}

总结:二维数组传参,形参可以写成数组,也可以写成指针
在这里插入图片描述

4.函数指针变量

先看一段代码

#include<stdio.h>
void test()
{printf("hehe\n");
}
int main()
{printf("test: %p\n", test);printf("&test: %p\n", &test);return 0;
}

在这里插入图片描述

所以为了存放函数地址,就有了函数指针变量

void test()
{printf("hehe\n");
}
void(*pf1)() = &test;
void (*pf2)() = test;int Add(int x, int y)
{return x + y;
}
void(*pf3)(int, int) = Add;
void(*pf4)(int x, int y) = &Add;//x和y写上和省略都是可以的

在这里插入图片描述
一个例子

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

在这里插入图片描述**加粗样式**

两段有趣 的代码
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
都出自《c陷阱和缺陷》

typedef 关键字

在这里插入图片描述
如果是指针类型,能否重命名呢?其实也是可以的,⽐如,将int*重命名为 ptr_t,这样写:
在这里插入图片描述
但是对于数组指针和函数指针稍微有点区别:
⽐如我们有数组指针类型int(*)[5] ,需要重命名为parr_t,那可以这样写
在这里插入图片描述
新类型名 要在*右边
函数指针类型的重命名也是⼀样的,⽐如,将 void(*)(int)类型重命名为 pf_t,就可以这样写:

在这里插入图片描述

在这里插入图片描述
上面第二段有趣代码的简化

5.函数指针数组

以下哪个会是正确写法呢
在这里插入图片描述
答案是:parr1
parr1 先和 [] 结合,说明 parr1是数组,数组的内容是什么呢?
int (*)()类型的函数指针。

6.转移表

在这里插入图片描述

函数指针用途:转移表
举例:计算器的一般实现

#include <stdio.h>int add(int a, int b)
{return a + b;
}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 ret = 0;int input= 1;int X, Y;do{printf("1:add 2:sub 3:mul 4:div 0:exit\n");scanf("%d", &input);printf("Enter the value of X: ");scanf("%d", &X);printf("Enter the value of Y: ");scanf("%d", &Y);switch (input) {case 1:ret = add(X, Y);break;case 2:ret = sub(X, Y);break;case 3:ret = mul(X, Y);break;case 4:ret = div(X, Y);break;case 0:printf("退出程序\n");break;default:printf("Invalid option");break;}printf("%d\n", ret);}while(input);return 0;
} 

使用函数指针数组来实现

#include <stdio.h>int add(int a, int b)
{return a + b;
}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 ret = 0;int input = 1;int x, y;int(*p[5])(int x, int y) = { 0,add,sub,mul,div };do{printf("1:add 2:sub 3:mul 4:div 0:exit\n");scanf("%d", &input);if ((input <= 4 && input >= 1)){printf("请输入操作数\n");scanf("%d %d", &x, &y);ret = (*p[input])(x, y);printf("ret = %d\n", ret);}else if (input == 0){printf("退出计算机\n");}else{printf("输入有误\n");}}while(input);return 0;
}

未完待续…
在这里插入图片描述
在这里插入图片描述

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

如若内容造成侵权/违法违规/事实不符,请联系瞎胡闹网进行投诉反馈,一经查实,立即删除!

相关文章

bash: docker-compose: 未找到命令

bash: docker-compose: 未找到命令 在一台新的服务器上使用 docker-compose 命令时&#xff0c;报错说 docker-compose 命令找不到&#xff0c;在网上试了一些安装方法&#xff0c;良莠不齐&#xff0c;所以在这块整理一下&#xff0c;如何正确快速的安装 docker-compose cd…

Linux 进程间通信 System V系列: 共享内存,信号量,简单介绍消息队列

进程间通信 System V系列: 共享内存,初识信号量 一.共享内存1.引入2.原理3.系统调用接口1.shmget2.shmat和shmdt3.shmctl 4.边写代码边了解共享内存的特性1.ftok形成key,shmget创建与获取共享内存2.shm相关指令3.shmat和shmdt挂接和取消挂接4.shmctl获取共享内存信息,释放共享内…

判断字符是否唯一——力扣

面试题 01.01. 判定字符是否唯一 已解答 简单 相关标签 相关企业 提示 实现一个算法&#xff0c;确定一个字符串 s 的所有字符是否全都不同。 示例 1&#xff1a; 输入: s "leetcode" 输出: false 示例 2&#xff1a; 输入: s "abc" 输出: true…

Vue项目npm install certificate has expired报错解决方法

1.Vue项目 npm install 安装依赖突然报错&#xff1a; npm ERR! code CERT_HAS_EXPIRED npm ERR! errno CERT_HAS_EXPIRED npm ERR! request to https://registry.npm.taobao.org/zrender/download/zrender-4.3.0.tgz failed, reason: certificate has expired npm ERR! A com…

Xilinx 千兆以太网TEMAC IP核简介

Xilinx 公司提供了千兆以太网MAC控制器的可参数化LogiCORET™IP解决方案&#xff0c;通过这个IPCore可以实现FPGA与外部网络物理层芯片的互连。基于Xilinx FPGA 的以太网设计&#xff0c;大大降低了工程的设计复杂度&#xff0c;缩短了开发周期&#xff0c;加快了产品的面市速度…

金南瓜EAP库使用开发

前言 最近做了 一个半导体公司的上位机开发。厂商要求要支持EAP通讯。 先了解一下EAP是什么吧&#xff1f;百度资料 EAP&#xff08; Equipment Automation Program&#xff09;设备自动化处理&#xff0c;工厂实现设备自动化生产和管理。 1. 机台状态数据收集&#xff0c;包…

网络编程——Socket——模拟用户登录

功能一&#xff1a;模拟用户登录 功能二&#xff1a;实现客户发送登录用户信息&#xff0c;服务器端显示登录信息并响应给客户端登录成功 这里设置的用户登录信息为&#xff1a;admin&#xff0c;123456 实现&#xff1a; 1.首先&#xff0c;服务端创建并启动服务器&#x…

JINGWHALE 虚拟现实物质与空间理论 —— 全息世界

JINGWHALE 对此论文相关未知以及已知概念、定理、公式、图片等内容的感悟、分析、创新、创造等拥有作品著作权。未经 JINGWHALE 授权&#xff0c;禁止转载与商业使用。 一、虚拟现实物质与空间理论 物质是由离散的奇点JING粒子&#xff0c;依据不同的维度粒度&#xff0c;通过…

SSM【Spring SpringMVC Mybatis】——Mybatis(二)

如果对一些基础理论感兴趣可以看这一期&#x1f447; SSM【Spring SpringMVC Mybatis】——Mybatis 目录 1、Mybatis中参数传递问题 1.1 单个普通参数 1.2 多个普通参数 1.3 命名参数 1.4 POJO参数 1.5 Map参数 1.6 Collection|List|Array等参数 2、Mybatis参数传递【#与…

【全开源】JAVA台球助教台球教练多端系统源码支持微信小程序+微信公众号+H5+APP

功能介绍 球厅端&#xff1a;球厅认证、教练人数、教练的位置记录、助教申请、我的项目、签到记录、我的钱包、数据统计 教练端&#xff1a;我的页面&#xff0c;数据统计、订单详情、保证金、实名认证、服务管理、紧急求助、签到功能 用户端&#xff1a;精准分类、我的助教…

第八章小程序后端开发,运用Bmob后端云

比目后端云简介 一个完整的小程序系统&#xff0c;不但需要前端的展现&#xff0c;而且需要后端服务器的支撑&#xff0c;以提供数据服务。也就是说&#xff0c;开发一个真正完整的小程序应用&#xff0c;需要前后端的相互配合。小程序与远程服务器之间通过HTTPS传输协议进行数…

Spring框架学习笔记(二):Spring IOC容器配置 Bean,分别基于XML配置bean 和 基于注解配置 bean

1 Spring 配置/管理 bean 介绍 Bean 管理包括两方面 &#xff1a;创建 bean 对象&#xff1b;给 bean 注入属性 Bean 配置方式&#xff1a;基于 xml 文件配置方式&#xff1b;基于注解方式 2 基于 XML 配置 bean 2.1 通过类型来获取 bean 方法&#xff1a;给getBean传入一…

linux fdisk 银河麒麟操作系统 v10 磁盘分区和挂载 详细教程

1查看 未加载的磁盘 fdisk -l 2 开始分区 fdisk /dev/vdb #查看分区 #新建分区和保存 3 格式化和挂载 fdisk -l mkfs.xfs /dev/vdb1 #查看uuid blkid /dev/vdb1 mkdir /data vi /etc/fstab UUID209daa-fb1c-48f2-bf5e-e63f38cb8a /data xfs defaults 0 0 #加载下 mo…

Vue 中动态与静态处理 Element UI/Element Plus 组件禁用状态样式

目录 一、静态样式修改 - 使用 ::v-deep 穿透组件样式二、选择器的优先级和匹配顺序三、动态添加样式 - 使用 Vue 实例属性&#xff08;非推荐&#xff09;四、区别总结五、应用场景总结 本文主要探讨在 Vue.js 项目中&#xff0c;特别是搭配 Element UI 或 Element Plus 组件库…

NVME协议第四章-Data Structures

本章描述NVME所需的数据结构&#xff08;讨论均基于PCIE over NVME&#xff09;。 一、Submission Queue & Completion Queue Definition host提交cmd到SQ&#xff0c;填入SQ后&#xff0c;Tail指针需要1&#xff0c;如果tail指针超过队列queue size&#xff0c;那么tai…

Springboot+Vue项目-基于Java+MySQL的车辆管理系统(附源码+演示视频+LW)

大家好&#xff01;我是程序猿老A&#xff0c;感谢您阅读本文&#xff0c;欢迎一键三连哦。 &#x1f49e;当前专栏&#xff1a;Java毕业设计 精彩专栏推荐&#x1f447;&#x1f3fb;&#x1f447;&#x1f3fb;&#x1f447;&#x1f3fb; &#x1f380; Python毕业设计 &…

TVM简介

TVM FGPA,CPU, GPU 1.什么是TVM&#xff1f; 是一个支持GPU&#xff0c;CPU&#xff0c;FPGA指令生成的开源编译器框架 2.特点 基于图和算符结构来优化指令生成&#xff0c;最大化硬件执行效率。其中使用了很多方法 来改善硬件执行速度&#xff0c;包括算符融合、数据规划…

LeetCode96:不同的二叉搜索树

题目描述 给你一个整数 n &#xff0c;求恰由 n 个节点组成且节点值从 1 到 n 互不相同的 二叉搜索树 有多少种&#xff1f;返回满足题意的二叉搜索树的种数。 代码 /*dp[i]&#xff1a;表示i个节点有dp[i]个不同的二搜索叉树递推公式&#xff1a;dp[i] dp[j-1] * dp[i-j], j…

【C语言—猜数字小游戏】

一、游戏规则 电脑自动生成一个1~100范围内的随机数&#xff0c;由玩家猜测本轮生成的随机数是什么&#xff0c;系统根据玩家猜测数据的⼤⼩给出猜⼤了或猜⼩了的反馈&#xff0c;直到玩家猜对&#xff0c;游戏结束。 如何生成随机数&#xff1a;【C语言】/*如何生成随机值*/-C…

嵌入式学习70-复习(wireshark使用和http协议)

--------------------------------------------------------------------------------------------------------------------------------- wireshark 1.sudo wireshark 2.选择 any &#xff0c; 3.搜索 http/tcp 54 为 发送的数据包 58 回复的数据包 请求报文 请求报文…