C语言_指针进阶(下)

文章目录

  • 前言
  • 一、函数指针数组
  • 二、指向函数指针数组的指针
  • 三. 回调函数
  • 四. qsort 函数
  • 五. 数组名的理解 sizeof
    • 5.1 数组名的理解(二维数组)
      • 5.1.1 数组名的理解 strlen
      • 5.1.2 例题:
        • 例一.
        • 例二.
        • 例三.
        • 例四.


前言


一、函数指针数组

数组是一个存放相同类型数据的存储空间,
那把函数的地址存放到一个数组中,那这个数组就叫函数指针数组
提示:以下是代码样例,下面案例可供参考

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;
}
//计算器
void  menu()
{printf("************************\n");printf("*****1. Add 2. Sub *****\n");printf("*****3. Mul 4. Div *****\n");printf("*****  0. exit  ********\n");printf("************************\n");
}int main()
{int x = 0;int y = 0;int ret = 0;int input = 0;//定义一个函数指针数组int (*pfArr[5])(int, int) = { NULL,Add,Sub,Mul,Div };//                             0     1   2   3   4do{menu();printf("请选择:>\n");scanf("%d", &input);if (input >= 1 && input <= 4){printf("请输入两个操作数:");scanf("%d %d", &x, &y);ret = pfArr[input](x, y);printf("ret = %d\n", ret);}else if (input = 0){printf("退出计算器\n");}else{printf("选择错误,重新选择\n");}} while (input);return 0;
}

二、指向函数指针数组的指针

三. 回调函数

回调函数就是一个通过函数指针调用的函数,如果你把函数的指针(地址)作为参数传递给另一个函数,当这个指针被用来调用其所指向的函数时,我们就说这是回调函数。
回调函数不是由该函数的实现方直接调用,而是在特定的事件或条件发生时有另外的一方调用的,用于对该事件或条件进行响应。

四. qsort 函数

qsort 是标准库函数,用于对数组中的元素进行快速排序。它通过比较两个元素的大小来确定它们的顺序。以下是 qsort 函数的定义:

void qsort(void *base, size_t count, size_t size, int (*compare)(const void *, const void *));

参数说明:

  • base:指向要排序的数组的第一个元素的指针。
  • count:要排序的元素数量。
  • size:每个元素的字节数。
  • compare:一个比较函数,用于比较两个元素的大小。该函数返回一个整数值,指示两个元素的顺序关系。如果返回负数,则表示第一个元素应该排在第二个元素的前面;如果返回正数,则表示第一个元素应该排在第二个元素的后面;如果返回 0,则表示两个元素相等。

使用 qsort 函数时,需要自定义一个比较函数,根据实际需要对元素进行比较。以下是一个简单的示例:

#include <stdio.h>
#include <stdlib.h>int compare(const void *a, const void *b) {return (*(int*)a - *(int*)b);
}int main() {int arr[] = {3, 1, 4, 2, 5};int n = sizeof(arr) / sizeof(int);qsort(arr, n, sizeof(int), compare);for (int i = 0; i < n; i++) {printf("%d ", arr[i]);}printf("\n");return 0;
}

输出结果为:1 2 3 4 5,表示数组已经按从小到大的顺序排好了序。qsort 是标准库函数,用于对数组中的元素进行快速排序。它通过比较两个元素的大小来确定它们的顺序。以下是 qsort 函数的定义:

void qsort(void *base, size_t count, size_t size, int (*compare)(const void *, const void *));

参数说明:

  • base:指向要排序的数组的第一个元素的指针。
  • count:要排序的元素数量。
  • size:每个元素的字节数。
  • compare:一个比较函数,用于比较两个元素的大小。该函数返回一个整数值,指示两个元素的顺序关系。如果返回负数,则表示第一个元素应该排在第二个元素的前面;如果返回正数,则表示第一个元素应该排在第二个元素的后面;如果返回 0,则表示两个元素相等。

使用 qsort 函数时,需要自定义一个比较函数,根据实际需要对元素进行比较。以下是一个简单的示例:

#include <stdio.h>
#include <stdlib.h>int compare(const void *a, const void *b) {return (*(int*)a - *(int*)b);
}int main() {int arr[] = {3, 1, 4, 2, 5};int n = sizeof(arr) / sizeof(int);qsort(arr, n, sizeof(int), compare);for (int i = 0; i < n; i++) {printf("%d ", arr[i]);}printf("\n");return 0;
}

输出结果为:1 2 3 4 5,表示数组已经按从小到大的顺序排好了序。qsort 是标准库函数,用于对数组中的元素进行快速排序。它通过比较两个元素的大小来确定它们的顺序。以下是 qsort 函数的定义:

void qsort(void *base, size_t count, size_t size, int (*compare)(const void *, const void *));

参数说明:

  • base:指向要排序的数组的第一个元素的指针。
  • count:要排序的元素数量。
  • size:每个元素的字节数。
  • compare:一个比较函数,用于比较两个元素的大小。该函数返回一个整数值,指示两个元素的顺序关系。如果返回负数,则表示第一个元素应该排在第二个元素的前面;如果返回正数,则表示第一个元素应该排在第二个元素的后面;如果返回 0,则表示两个元素相等。

使用 qsort 函数时,需要自定义一个比较函数,根据实际需要对元素进行比较。以下是一个简单的示例:

#include <stdio.h>
#include <stdlib.h>int compare(const void *a, const void *b) {return (*(int*)a - *(int*)b);
}int main() {int arr[] = {3, 1, 4, 2, 5};int n = sizeof(arr) / sizeof(int);qsort(arr, n, sizeof(int), compare);for (int i = 0; i < n; i++) {printf("%d ", arr[i]);}printf("\n");return 0;
}

输出结果为:1 2 3 4 5,表示数组已经按从小到大的顺序排好了序。

五. 数组名的理解 sizeof

提示:以下是代码样例,下面案例可供参考

char arr[] = "abcdef";//[a b c d e f \0]printf("%d\n", sizeof(arr));//7//char [7]printf("%d\n", sizeof(arr + 0));//arr + 0是首元素的地址   4printf("%d\n", sizeof(*arr));//*arr其实就是首元素,1个字节   //*arr--> *(arr+0) -- arr[0]printf("%d\n", sizeof(arr[1]));//arr[1]是第二个元素,1个字节   printf("%d\n", sizeof(&arr));//&arr是数组的地址,是地址就是4/8个字节printf("%d\n", sizeof(&arr + 1));//&arr + 1是跳过一个数组的地址,4/8printf("%d\n", sizeof(&arr[0] + 1));//&arr[0] + 1是第二个元素的地址 4/8

 printf("%d\n", sizeof(p));//p是一个指针变量 大小就是4/8printf("%d\n", sizeof(p + 1));//p+1是'b'的地址,是地址大小就是4/8个字节printf("%d\n", sizeof(*p));//*p 就是'a',就是1个字节printf("%d\n", sizeof(p[0]));//p[0]--> *(p+0) --> *p  1个字节printf("%d\n", sizeof(&p));//4/8   &p -- char**printf("%d\n", sizeof(&p + 1));//4/8printf("%d\n", sizeof(&p[0] + 1));//4/8 , &p[0] + 1得到是'b'的地址 

5.1 数组名的理解(二维数组)

5.1.1 数组名的理解 strlen

特点


提示:以下是代码样例,下面案例可供参考

int main()
{char arr[] = { 'a','b','c','d','e','f' };printf("%d\n", strlen(arr));//因为字符数组arr中没有\0,所以在求字符串长度的时候,会一直往后找,产生的结构就是随机值printf("%d\n", strlen(arr + 0));//arr + 0是首元素的地址,和第一个一样,也是随机值printf("%d\n", strlen(*arr));//err(错误的写法), arr是数组首元素的地址,*arr就是数组首元素,就是'a'-97//strlen函数参数的部分需要传一个地址,当我们传递的是'a'时,'a'的ASCII码值是97,那就是将97作为地址传参//strlen就会从97这个地址开始统计字符串长度,这就非法访问内存了//printf("%d\n", strlen(arr[1]));//errprintf("%d\n", strlen(&arr));//&arr是数组的地址,数组的地址和数组首元素的地址,值是一样的,那么传递给strlen函数后,依然是从数组的第一个元素的位置开始往后统计printf("%d\n", strlen(&arr + 1));//随机值printf("%d\n", strlen(&arr[0] + 1));//&arr[0] + 1是第二个元素的地址。结果也是随机值return 0;
}
char* p = "abcdef";//     012345printf("%d\n", strlen(p));//6printf("%d\n", strlen(p + 1));//5//printf("%d\n", strlen(*p));//err//printf("%d\n", strlen(p[0]));//errprintf("%d\n", strlen(&p));//随机值  编译器会随机给他分配地址printf("%d\n", strlen(&p + 1));//随机值  &p+1  与  &p  没有差异,没啥关系printf("%d\n", strlen(&p[0] + 1));//5
int a[3][4] = { 0 };printf("%d\n", sizeof(a));//3*4*4 = 48printf("%d\n", sizeof(a[0][0]));//4  零行零列的元素printf("%d\n", sizeof(a[0]));//a[0]是第一行这个一维数组的数组名//数组名算是单独放在sizeof内部了,计算的是整个数组的大小,大小是16个字节printf("%d\n", sizeof(a[0] + 1));//?//a[0]作为第一行的数组名,没有单独放在sizeo内部,没有&//a[0]表示数组首元素的地址,也就是a[0][0]的地址//所以a[0]+1是第一行第二个元素的地址,是地址就是4/8个字节printf("%d\n", sizeof(*(a[0] + 1)));//4//计算的是就是第一行第2个元素的大小printf("%d\n", sizeof(a + 1));//4 / 8//a是数组首元素的地址,是第一行的地址 int(*)[4]//a+1 就是第二行的地址printf("%d\n", sizeof(*(a + 1)));//16//*(a+1) --> a[1] -> sizeof(*(a+1))->sizeof(a[1]) 计算的是第二行的大小//a+1 --> 是第二行的地址,int(*)[4]//*(a+1) 访问的第二行的数组printf("%d\n", sizeof(&a[0] + 1));//4/8//&a[0]是第一行的地址 int(*)[4]//&a[0]+1 是第二行的地址 int(*)[4]printf("%d\n", sizeof(*(&a[0] + 1)));//16 计算的是第二行的大小printf("%d\n", sizeof(*a));//计算的是第一行的大小-16//a是数组首元素的地址,就是第一行的地址//*a 就是第一行//*a --> *(a+0) --> a[0]printf("%d\n", sizeof(a[3]));//16//a[3]--> int [4]

5.1.2 例题:

例一.

例二.

例三.

例四.

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

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

相关文章

Ubuntu22.04配置WiFi

Ubuntu22.04配置WiFi 注意&#xff1a;在/etc/netplan/​下的配置文件&#xff0c;格式一定要正确&#xff0c;否则用sudo netplan try​的时候会报错 一、查看无线网卡的名称 //choice-1 ls /sys/class/net//choice-2 ip a//choice-3 ifconfig -a‍ 二、修改配置文件 文件…

为何红黑树在B/B+树之上仍然占据重要地位?

为何红黑树在B/B树之上仍然占据重要地位&#xff1f; 引言二、红黑树和B/B树的基本原理2.1、红黑树的特点和性质2.2、B/B树的特点和性质2.3、红黑树和B/B树的比较 三、B/B树相对于红黑树的优势四、红黑树仍然占据重要地位的原因总结 博主简介 &#x1f4a1;一个热爱分享高性能服…

openwrt开启SSH远程访问与开启WEB远程访问——三种方法

openwrt 开启SSH远程访问 首先&#xff0c;你的电脑用网线连接路由器LAN口是可以访问WEB页面和SSH连接的。 例如&#xff0c;电脑1连接Openwrt路由器&#xff0c;可以进行SSH连接到openwrt 路由器。但是电脑2无法远程访问Openwrt路由器网页和SSH远程连接。 本次操作固件版本…

2023年8月京东洗衣机行业品牌销售排行榜(京东数据挖掘)

鲸参谋监测的京东平台8月份洗衣机市场销售数据已出炉&#xff01; 根据鲸参谋平台的数据显示&#xff0c;8月份&#xff0c;京东平台上洗衣机的销量共计117万&#xff0c;环比增长约5%&#xff0c;同比下降约8%&#xff1b;销售额为18亿&#xff0c;环比下降约2%&#xff0c;同…

使用cpolar配合Plex搭建私人媒体站

文章目录 1.前言2. Plex网站搭建2.1 Plex下载和安装2.2 Plex网页测试2.3 cpolar的安装和注册 3. 本地网页发布3.1 Cpolar云端设置3.2 Cpolar本地设置 4. 公网访问测试5. 结语 1.前言 用手机或者平板电脑看视频&#xff0c;已经算是生活中稀松平常的场景了&#xff0c;特别是各…

ESP32-BOX的组件配置添加核心部分详细介绍

前言 &#xff08;1&#xff09;为了方便开发&#xff0c;ESP32提供了组件库方便用户进行二次开发。 github仓库&#xff1b;gitee仓库 &#xff08;2&#xff09;在学习本章之前最好有CMake或者Makefile的基础&#xff0c;如果没有也不要慌&#xff0c;有的话最好。 &#xff…

fcpx视频编辑处理 Final Cut Pro for Mac

Final Cut Pro是一款专业的视频剪辑软件&#xff0c;适用于Mac操作系统。Final Cut Pro X版本在视频剪辑方面进行了大规模的更新和改进&#xff0c;下面将介绍Final Cut Pro X中的一些主要功能和特性&#xff1a; Magnetic Timeline。这个新功能使得多条剪辑片段如同磁铁般吸合…

STM32 Cubemx 基本定时器Basic Timers

文章目录 前言简介Cubemx使用 前言 持续学习stm32中… 简介 基本定时器有TIM6和TIM7&#xff0c;是一个16位的向上定时器。基本定时器的用途较少&#xff0c;只能用于纯粹的定时器以及驱动DAC模块。 注&#xff1a;基本定时器各自独立&#xff0c;不存在共用的资源。 基本定…

修改el-card的header的背景颜色

修改el-card的header的背景颜色 1.修改默认样式 好处是当前页面的所有的el-card都会变化 页面卡片&#xff1a; <el-card class"box-card" ><div slot"header" class"clearfix"><span>卡片名称</span><el-button s…

【算法专题突破】滑动窗口 - 水果成篮(13)

目录 1. 题目解析 2. 算法原理 3. 代码编写 写在最后&#xff1a; 1. 题目解析 题目链接&#xff1a;904. 水果成篮 - 力扣&#xff08;Leetcode&#xff09; 题目有很长一段话&#xff0c;但是我们读一遍题目可以提炼转化出题目的要求 &#xff1a; 其实就是找出一个最长…

ArcGIS标注的各种用法和示例

标注是将描述性文本放置在地图中的要素上或要素旁的过程。 本文整理了ArcGIS中的各种标注方法、可能遇到的问题和细节,内容比较杂,想到哪写到哪。 一、正常标注某一字段值的内容 右键点击【属性】,在【标注】选项卡下勾选【标注此图层中的的要素】,在【文本字符串】栏中…

对话大模型中的情感支持及商业化落地

在1982年经典科幻电影《银翼杀手》中&#xff0c;仿生人瑞秋因为被植入记忆而以为自己是真人&#xff0c;当被告知自己是仿生人时&#xff0c;她拒绝相信&#xff0c;流下了眼泪。如今&#xff0c;随着AI领域对话大模型技术的发展&#xff0c;“比人更像真人”的人工智能正从梦…

【PHP】麻醉临床信息系统

麻醉临床信息系统以服务围术期临床业务工作的开展为核心&#xff0c;为医护人员、业务管理人员、院级领导提供流程化、信息化、自动化、智能化的临床业务综合管理平台。 麻醉信息系统处理的数据包含病人的手术信息、麻醉信息、病人手术过程中从监护仪上采集到的数据和病人情况等…

Git 版本控制系统 笔记

概念&#xff1a;一个免费开源&#xff0c;分布式的代码版本控制系统&#xff0c;帮助开发团队维护代码 作用&#xff1a;记录代码内容&#xff0c;切换代码版本&#xff0c;多人开发时高效合并代码内容【团队开发同一个项目的代码版本管理】 1、Git 安装 之前写了&#xff0…

Spring系列文章:Spring事务

一、事务简述 1、什么是事务&#xff08; Transaction&#xff08;tx&#xff09;&#xff09; 在⼀个业务流程当中&#xff0c;通常需要多条DML&#xff08;insert delete update&#xff09;语句共同联合才能完成&#xff0c;这 多条DML语句必须同时成功&#xff0c;或者同…

C++(day4)

思维导图 封装Mystring #include <iostream> #include<cstring>using namespace std;class Mystring{ public://无参构造函数Mystring():size(10){strnew char[size];strcpy(str,"");cout<<"无参构造函数"<<endl;}//有参构造函数…

怎么压缩pdf文件大小?详细压缩步骤

怎么压缩pdf文件大小&#xff1f;在日常的工作和学习中&#xff0c;我们频繁地处理PDF文件。然而&#xff0c;有时候这些文件的大小可能会非常庞大&#xff0c;这给我们带来了一系列的问题。首先&#xff0c;它们占用了大量的存储空间&#xff0c;使得我们的设备变得拥挤不堪。…

大话数据结构 1 绪论

数据:是描述客观事物的符号&#xff0c;是计算机中可以操作的对象&#xff0c;是能被计算机识别&#xff0c;并输入给计算机处理的符号集合。 数据元素:是组成数据的&#xff0c;有一定意义的基本单位&#xff0c;在计算机中通常作为整体处理&#xff0c;也被称为记录。 数据项…

使用SSH地址拉取远程仓库代码报下面的错误

说明&#xff1a;配置了SSH秘钥后&#xff0c;使用SSH地址克隆代码&#xff0c;依旧无法拉取代码&#xff0c;提示下面这个信息。 Their offer&#xff1a;ssh-rsa&#xff0c;ssh-dss fatal&#xff1a;Could not read from remote repository. Please make sure you have the…