【c语言指针详解】指针的高级应用

目录

一、指针和字符串

1.1 字符串和字符数组的关系

1.2 字符串常量和字符指针的使用

1.3 字符串函数库的指针参数

1.3.1 strlen 函数

1.3.2 strcpy 函数

1.3.3 strcat 函数

1.3.4 strcmp 函数

二、指针的高级应用

2.1 函数指针的定义和使用

2.2 回调函数和函数指针数组的应用

2.2.1 回调函数

2.2.2 函数指针数组


🌈嗨!我是Filotimo__🌈。很高兴与大家相识,希望我的博客能对你有所帮助。

🎁欢迎大家给我点赞👍、收藏⭐️,并在留言区📝与我互动,这些都是我前进的动力!

🌟我的格言:森林草木都有自己认为对的角度🌟。

一、指针和字符串

1.1 字符串和字符数组的关系

在 C 语言中,字符串是由字符组成的字符数组,以空字符(‘\0’,ASCII 值为 0)作为结尾。

下面是一个示例代码,演示了字符串和字符数组的关系:

#include <stdio.h>
#include <string.h>

int main() {
    // 直接初始化字符数组
    char str1[] = "Hello, World!";

    // 声明字符数组并赋值
    char str2[15];
    str2[0] = 'H';
    str2[1] = 'e';
    str2[2] = 'l';
    str2[3] = 'l';
    str2[4] = 'o';
    str2[5] = '\0';  // 字符串的结尾需要加上空字符

    printf("str1: %s\n", str1);
    printf("str2: %s\n", str2);

    // 通过字符数组逐个字符访问和修改字符串
    str1[7] = 'w';
    printf("Modified str1: %s\n", str1);

    // 使用字符数组进行字符串拼接
    char str3[30] = "Welcome ";
    char name[] = "Alice";
    strcat(str3, name);
    printf("str3: %s\n", str3);

    return 0;
}

输出结果如下:

1.2 字符串常量和字符指针的使用

在 C 语言中,字符串常量是由连续的字符组成的字符数组,以空字符 '\0' 结束。字符串常量使用双引号 " 括起来。例如:

char str[] = "Hello, World!"; // 字符数组,其内容为字符串常量

字符串常量在内存中被存储为只读数据,在大多数情况下,不能对其进行修改。因此,通常将字符串常量声明为字符指针(const char* 类型),来指向字符串常量的首地址。例如:

const char* str = "Hello, World!"; // 字符指针,指向字符串常量

以下是一个关于字符串常量和字符指针的使用示例代码:

#include <stdio.h>

int main() {
    // 声明字符串常量
    char str1[] = "Hello, World!"; // 字符数组
    const char* str2 = "Hello, World!"; // 字符指针

    printf("str1: %s\n", str1);
    printf("str2: %s\n", str2);

    // 使用字符指针访问字符串
    char* ptr = str1; // 字符指针指向字符数组
    while (*ptr != '\0') {
        printf("%c", *ptr);
        ptr++;
    }
    printf("\n");

    return 0;
}

输出结果如下:

1.3 字符串函数库的指针参数

C 语言提供了一组字符串函数库(如 <string.h>)来操作字符串。 这些字符串函数通常使用指针参数来接收和处理字符串数据。例如strlen、strcpy、strcat、strcmp 等。

1.3.1 strlen 函数

strlen 函数接受一个指向字符串的指针,并返回该字符串的长度,即字符的个数。

示例代码:

#include <stdio.h>
#include <string.h>

int main() {
    char str[] = "Hello,WeTab!";

    size_t len = strlen(str);
    printf("Length of the string: %zu\n", len);

    return 0;
}

输出结果如下:

注意:strlen 函数只计算字符串中的字符数目,不包括字符串末尾的空字符 \0。这是因为在 C 语言中,字符串以空字符作为结束标志。

1.3.2 strcpy 函数

strcpy 函数接受两个参数,一个目标字符串和一个源字符串的指针。它将源字符串中的内容复制到目标字符串中,并返回目标字符串的指针。

示例代码:

#include <stdio.h>
#include <string.h>

int main() {
    char source[] = "Hello, WeTab!";
    char destination[50];

    strcpy(destination, source);
    printf("Copied string: %s\n", destination);

    return 0;
}

输出结果如下:

注意:strcpy 函数会将源字符串中的内容复制到目标字符串中,包括末尾的空字符 \0。因此,在目标字符串中需要有足够的空间来存储源字符串的内容。建议在使用 strcpy 函数时,确保目标字符串足够大,以避免发生缓冲区溢出的问题。

1.3.3 strcat 函数

strcat 函数接受两个参数,一个目标字符串和一个源字符串的指针。它将源字符串中的内容追加到目标字符串的末尾,并返回目标字符串的指针。

示例代码:

#include <stdio.h>
#include <string.h>

int main() {
    char destination[50] = "Hello,";
    char source[] = " WeTab!";

    strcat(destination, source);
    printf("Concatenated string: %s\n", destination);

    return 0;
}

输出结果如下:

注意:strcat 函数会将源字符串中的内容追加到目标字符串的末尾,并在末尾加上空字符 \0。因此,在使用 strcat 函数之前,目标字符串必须以空字符结尾,并且有足够的空间来存储源字符串的内容和终止空字符。此外,类似 strcpy 函数,使用 strcat 函数时也应注意目标字符串的长度和避免发生缓冲区溢出的问题。

1.3.4 strcmp 函数

strcmp 函数接受两个参数,两个字符串的指针。它将两个字符串进行比较,并返回一个整数:
如果 str1 按照字典序小于 str2,返回负数;
如果 str1 等于 str2,返回 0;
如果 str1 按照字典序大于 str2,返回正数。

示例代码:

#include <stdio.h>
#include <string.h>

int main() {
    char str1[] = "hello";
    char str2[] = "world";
    char str3[] = "hello";
    
    int result1 = strcmp(str1, str2);
    int result2 = strcmp(str1, str3);
    
    printf("strcmp(str1, str2) 返回值: %d\n", result1);
    printf("strcmp(str1, str3) 返回值: %d\n", result2);
    
    return 0;
}

输出结果如下:

二、指针的高级应用

2.1 函数指针的定义和使用

函数指针是指向函数的指针,可以将其视为指向包含函数代码的内存位置的指针。

函数指针的类型定义为:返回类型 (*指针变量名)(参数列表)。

可以通过名称或指针来调用函数,函数指针可以用来动态调用函数。

示例代码:

#include <stdio.h>

// 声明一个函数指针类型
typedef int (*Operation)(int, int);

// 定义加法函数
int add(int a, int b) {
    return a + b;
}

// 定义减法函数
int subtract(int a, int b) {
    return a - b;
}

int main() {
    // 定义函数指针变量
    Operation op;
    
    // 把函数赋值给函数指针变量
    op = add;
    
    // 通过指针变量调用函数
    int result = op(5, 3);
    printf("加法的结果: %d\n", result);
    
    // 修改指针变量的值,指向减法函数
    op = subtract;
    
    // 通过指针变量调用函数
    result = op(5, 3);
    printf("减法的结果: %d\n", result);
    
    return 0;
}

输出结果如下:

2.2 回调函数和函数指针数组的应用

2.2.1 回调函数

回调函数是指当我们调用一个函数时,把另一个函数的指针作为一个参数传递给它,在这个函数完成后再调用这个指针所指向的函数,这就是回调函数。

示例代码:

#include <stdio.h>

// 回调函数类型
typedef void (*Callback)(int);

// 函数指针变量数组类型
typedef Callback CallbackArray[3];

// 回调函数实现
void my_callback(int number) {
    printf("回调函数被调用,参数为:%d\n", number);
}

// 调用函数
void call_function(Callback callback_func) {
    printf("调用函数执行...\n");
    callback_func(123);
    printf("调用函数结束。\n");
}

int main() {
    // 使用回调函数
    printf("使用回调函数:\n");
    call_function(my_callback);
    
    // 使用函数指针数组
    printf("使用函数指针数组:\n");
    CallbackArray callbacks = { my_callback, my_callback, my_callback };
    callbacks[0](1);
    callbacks[1](2);
    callbacks[2](3);
    
    return 0;
}

输出结果如下:

2.2.2 函数指针数组

函数指针数组是指向函数指针的指针数组,可以用于存储多个函数指针。

函数指针数组的声明方式如下:

ReturnType (*FunctionName[])(ParameterTypes) = {Function1, Function2, ..., FunctionN};

其中,ReturnType表示函数的返回类型,FunctionName表示函数指针数组的名称,ParameterTypes表示函数的参数类型,Function1FunctionN表示要存储在数组中的函数指针。

示例代码:

#include <stdio.h>

// 函数原型
void Function1();
void Function2();
void Function3();

int main() {
    // 定义函数指针数组
    void (*functionPointers[])(void) = {Function1, Function2, Function3};

    // 调用函数指针数组中的函数
    functionPointers[0](); // 调用Function1
    functionPointers[1](); // 调用Function2
    functionPointers[2](); // 调用Function3

    return 0;
}

void Function1() {
    printf("This is Function1.\n");
}

void Function2() {
    printf("This is Function2.\n");
}

void Function3() {
    printf("This is Function3.\n");
}

输出结果如下:

函数指针数组在C语言中经常用于实现回调机制和多态。通过存储不同函数的指针,我们可以在运行时动态地选择执行不同的函数,从而实现程序的可扩展性和灵活性。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

2022年第十一届数学建模国际赛小美赛D题野生动物贸易是否应长期禁止解题全过程文档及程序

2022年第十一届数学建模国际赛小美赛 D题 野生动物贸易是否应长期禁止 原题再现&#xff1a; 野生动物市场被怀疑是此次疫情和2002年SARS疫情的源头&#xff0c;食用野生肉类被认为是非洲埃博拉病毒的一个来源。在冠状病毒爆发后&#xff0c;中国最高立法机构永久性地加强了野…

基于SpringBoot的大学活动平台

✌全网粉丝20W,csdn特邀作者、博客专家、CSDN新星计划导师、java领域优质创作者,博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌ &#x1f345;文末获取项目下载方式&#x1f345; 一、项目背景介绍&#xff1a; 随着互联网技术的不断…

如何统计12.5米高程覆盖率?

无论是卫星影像还是高程DEM数据&#xff0c;覆盖率都是大家非常关心的一个重要参数。 我们曾基于WGS84坐标进行过简单的覆盖率计算&#xff0c;而且面积还包括了海洋区域。 因此&#xff0c;最后得出了一个非常不靠谱&#xff0c;看起来也很不漂亮的数据&#xff1a;12%。 为…

【算法】对二分搜索的理解

二分搜索大家都很熟悉&#xff0c;首先我们先来看看基本框架 func binarySearch(nums []int, target int) int {left, right : 0, ...for ... {mid : left (right-left)/2if nums[mid] target {...} else if nums[mid] < target {left ...} else if nums[mid] > targ…

快速安装Axure RP Extension for Chrome插件

打开原型文件的html&#xff0c;会跳转到这个页面&#xff0c;怎么破&#xff1f; 我们点开产品设计的原型图如果没有下载Axure插件是打不开&#xff0c;而我们国内网通常又不能再google商店搜索对应插件&#xff0c;下面教大家如何快速安装 1、打开原型文件->resources-&g…

星钻图形输出

答案&#xff1a; #include <stdio.h> int a 0, b 0; void printLine(int a , int b) //输出一行包含&#xff1a;若干个空格 若干个*&#xff0c;第一&#xff0c;二个参数为空格数和*数&#xff1b; (定义一个星钻输出函数) {while (a--) //打印a个空格{printf(…

内衣洗衣机和手洗哪个干净?高性价比内衣洗衣机推荐

通常来说&#xff0c;我们的内衣裤对卫生要求比较高&#xff0c;毕竟是贴身穿的&#xff0c;所以如果和一般的衣物一起洗&#xff0c;就怕会有细菌互相感染。所以很多用户为了内衣裤的卫生都会选择自己手动洗&#xff0c;但手洗一方面很费时间和人力&#xff0c;另一方面又很伤…

el-menu标题过长显示不全问题处理

项目基于vue-element-admin 问题 期望 处理方式 \src\layout\components\Sidebar\index.vue 文件后添加CSS <style scped> /* 侧栏导航菜单经典 文字超长溢出问题 CSS折行 */ .el-submenu__title {display: flex;align-items: center; } .el-submenu__title span {white-…

刚毕业做前端开发难度会很大吗

这里是up主的三段经历&#xff0c;小伙伴们可以自己看一看 首先可以确定的是&#xff0c;不是很大&#xff0c;因为如果你能走到做开发这一步去&#xff0c;说明你的基础能力是够硬的 我的第一段经历&#xff0c;也就是我的第一份实习&#xff0c;是一家小企业&#xff0c;一共…

单片机第三季-第六课:STM32标准库

1&#xff0c;为什么会有标准外设库 传统单片机软件开发方式&#xff1a; (1)芯片厂商提供数据手册、示例代码、开发环境&#xff1b; (2)单片机软件工程师面向产品功能&#xff0c;查阅数据手册&#xff0c;参考官方示例代码进行开发&#xff1b; (3)硬件操作的方式是用C语言…

软件设计中如何画各类图之六状态图:生动呈现对象生命周期状态转换的重要工具

目录 1 状态图简介2 状态图的符号及说明2.1 状态&#xff08;State&#xff09;2.2 转移&#xff08;Transition&#xff09;2.3 起始状态与终止状态2.4 动作&#xff08;Action&#xff09; 3 画状态图的步骤3.1 确定对象3.2 定义状态3.3 标识转移3.4 标注动作3.5 添加起始和结…

万宾科技智能水环境综合治理监测系统效果

水环境综合治理是一项旨在全面改善水环境质量的系统工程。它以水体为对象&#xff0c;综合考虑各种因素&#xff0c;通过科学规划和技术手段&#xff0c;解决水环境污染、生态退化等问题&#xff0c;核心理念是“统一规划、分步实施&#xff1b;标本兼治&#xff0c;重在治本&a…

C#事件的本质

event字段本质就是对委托进行私有访问限制&#xff0c;事件的本质就是委托&#xff0c;只不过系统会对用event字段修饰的委托进行了特殊处理&#xff0c;比如自动生成一个私有的委托变量&#xff0c;添加两个事件访问器&#xff0c;同时禁止外部类对事件的Invoke等方法调用。 …

Spring Cache【娓娓道来】

目录​​​​​​​ 1.自我介好&#x1f633;&#x1f633;&#x1f633; 2.常用注解 &#x1f495;&#x1f495;&#x1f495; 3.EnableCaching&#x1f926;‍♂️&#x1f926;‍♂️&#x1f926;‍♂️ 4.CachePut&#x1f937;‍♀️&#x1f937;‍♀️&#x1f93…

虚拟数据优化器VDO

本章主要介绍虚拟化数据优化器。 什么是虚拟数据优化器VDO创建VDO设备以节约硬盘空间 了解什么是VDO VDO全称是Virtual Data Optimize&#xff08;虚拟数据优化)&#xff0c;主要是为了节省硬盘空间。 现在假设有两个文件file1和 file2&#xff0c;大小都是10G。file1和 f…

定时器的使用及实现

在Java中&#xff0c;定时器&#xff08;Timer&#xff09;是一个用于执行任务的工具类。它可以安排任务在指定的时间点执行&#xff0c;或者按照指定的时间间隔周期性地执行。 1. Timer类 Timer类位于java.util包中&#xff0c;它提供了一种简单而便利的方式来安排以后的任务…

AR + 通信,虚实结合让工作协同从线上到「现场」

在数字经济无所不在的当下&#xff0c;千行百业都与数智化办公接轨并因其实现转型升级。关注【融云 RongCloud】&#xff0c;了解协同办公平台更多干货。 升级的背后&#xff0c;是利用技术把工作用更自然的方式连接起来&#xff0c;让整个工作流协同更顺、体验更好。 而其中…

Dijkstra(迪杰斯特拉)算法

Dijkstra(迪杰斯特拉)算法的思想是广度优先搜索&#xff08;BFS&#xff09; 贪心策略。 是从一个顶点到其余各顶点的最短路径算法&#xff0c;节点边是不各自不同的权重&#xff0c;但都必须是正数 如果是负数&#xff0c;则需要 Bellman-Ford 算法 如果想求任意两点之间的距离…

占用站点资源,无法正常登录?这个功能帮助解决

在企业里随着PDM用户的增加PDM管理员是否发现原本的站点已经不够用出现部分用户占用站点资源导致其他用户无法正常登录导致该问题无法解决&#xff0c;本篇介绍PDM自动下线的功能助力企业解决问题&#xff0c;更好的帮助企业完成PDM的正常使用 今天我给大家带来的就是SOLIDWOR…

外网的maven项目转移到内网操作的步骤

1、新起一个仓库路径testRep&#xff0c;idea 引用的maven里的setting.xml里仓库配置修改成刚才建的路径&#xff0c;目的把需要的jar全部下载到那个文件夹里 2、项目打压缩包&#xff0c;刚才仓库文件夹打压缩包&#xff0c;并复制到内网电脑 3、内网电脑idea引入项目 4、修改…