C/C++指针之提高篇详解(二)
创始人
2024-04-14 08:46:08
0

一、引言

C/C++语言中引入了指针,使得程序能够直接访问内存地址,使得很多复杂的操作变得简单,同时也提高了程序的运行效率。指针即是地址,但是地址却是通过指针变量来存储的。这就好比我们的教室,每个教室都有一个房间号,一个房间号也对应着一间教室,此处的教室就是固定的地址(指针),其地址是通过房间号(指针变量)来表示的。地址就是指针,而房间号就是指针变量。
笔者在《C/C++指针入门详解(一)》一文中给出了指针的基础知识和基本用法。详见链接:
https://blog.csdn.net/sunnyoldman001/article/details/128061186?spm=1001.2014.3001.5502
本文给出了有关指针的更多应用场景及示例,例如函数指针、文件指针、更换数据类型、双指针等等。

二、指针的应用

1.根据需要改变内存中数据的数据类型
例1:在位域中,经常会根据需要把某单一变量存储到内存中,然后根据需要将其转换为结构体类型,进而可以进行一些复杂的操作,例如提取某个或某几个比特位上的数据等。
示例代码:

#include"stdio.h" 
struct weiyu
{unsigned char a:5;unsigned char b:2;unsigned char c:4;
};
int main()
{weiyu *p;unsigned short val = 1521;//10111110001//将存储变量a的地址赋值给指针变量p,并将内存中的数据类型改换为结构体 p = (struct weiyu*)&val;printf("weiyu a = %d\n", p->a);printf("weiyu b = %d\n", p->b);printf("weiyu c = %d\n", p->c);return 0;
}

运行结果:
在这里插入图片描述
说明:
本例中将低比特位0 ~ 4上的“10001”赋值为结构体成员a,因此a的值是17,将比特位5 ~ 6上的“11”赋值为结构体成员b,因此b的值是3,将比特位8 ~ 11上的“101”赋值为结构体成员c,因此c的值是5。比特位7上的“1”被舍弃。
2.文件指针
例2:打开某一文本文本,向屏幕输出该文件内容,并统计字符‘e’出现的次数。
参考代码:

#include "stdio.h"
#include "stdlib.h"
int main()
{FILE *fp;//文件指针char ch;int count = 0;//打开文件,并用文件指针fp指向文件的首地址if( ( fp = fopen("file.cpp", "rt" ) ) == NULL ){printf("Cannot open file!");exit(1);}ch = fgetc(fp);//从文件中读取一个字符while( ch != EOF ){putchar(ch);//向屏幕输出读到的字符if( ch == 'e' ){count++;}ch = fgetc(fp);}fclose(fp);//关闭文件printf( "\n字母e出现的次数:%d\n", count );return 0;
}

运行结果:
在这里插入图片描述
3.双指针
指针可以用来实现函数的双向传值功能,其原理类似于在把指针作为地址(可以看成是一个教室),地址里的内容可以根据需要进行修改(教室里的学生可以更换),以实现双向传值的功能。但是地址本身是不可以更改的(你不能把教室搬家)。但是有些时候还真就是希望可以把地址搬家,那么怎么办呢?其实可以利用双指针来实现,也就是把地址放入新的地址中,类似于在一个教学楼里,在房间号已经固定的情况下,为了满足某一种需要,而重新给教室分配房间号一样,如果把教室看成地址的话,那么教学楼就是一个二级地址,用来存储教室。当把教学楼作为地址单函数参数的话,那么该地址中的内容就可以根据需要随意修改了,这其实就是双指针。
例3:利用函数参数的形式交换两个指针的地址
参考代码:

#include"stdio.h"
#include"malloc.h"
void swap( int **p,int **q ); 
int main()
{int a, b, **p, **q;//首先给p和q分配空间,存储的是地址的地址 p = (int **)malloc( sizeof(int) );q = (int **)malloc( sizeof(int) );a = 1;b = 2;*p = &a;*q = &b;printf( "交换前地址:p: %x, q: %x\n", *p, *q );printf( "交换前的数据:p: %d, q: %d\n", **p, **q );swap( p, q );printf( "交换后地址:p: %x, q: %x\n", *p, *q );printf( "交换后的数据:p: %d, q: %d\n", **p, **q );return 0; 
}
//将p和q所指向地址中存储的地址进行交换 
void swap( int **p,int **q )
{  int *temp;temp = *p;*p   = *q;*q   = temp;
}

运行结果:
在这里插入图片描述
说明:此用法比较复杂,在双指针被使用前必须要初始化。用时要慎重!!!
4.函数指针
C语言中的函数指针是指向函数的指针变量。用法类似于C++的模板。
定义函数指针的一般形式为:

类型说明符 (*函数名)(形参表) ;

此函数仅仅是一个声明,无函数体。此处的“函数名”严格来说只是一个指针,它指向了某个函数的入口地址。
例4:利用函数指针实现求两个整数的最大值、最小值、和。
参考的代码:

#include"stdio.h" 
int max( int a, int b );
int min( int a, int b );
int sum( int a, int b );
int (*f)(int a, int b);
int main()
{int a = 1, b = 2;f = max;int c = (*f)( a, b );printf( "%2d 和 %2d 的最大值: %2d\n", a, b, c );f = min;c = (*f)( a, b );printf( "%2d 和 %2d 的最小值: %2d\n", a, b, c );f = sum;c = (*f)( a, b );printf( "%2d 和 %2d 的和:     %2d\n", a, b, c );return 0;
}int max( int a, int b )
{  return a > b ? a : b;  
}
int min( int a, int b )
{  return a > b ? b : a;  
}
int sum( int a, int b )
{return a + b;
}

运行结果:
在这里插入图片描述
5.指针数组
指针数组是指数组中的元素都是指针变量,即数组的元素都是地址。常用于字符串数组的操作。
指针数组的定义如下:

类型说明符 *指针变量名[长度];

例5:给定5个字符串,然后统计字符串的最大长度。
参考代码:

#include"stdio.h" 
#include"string.h"
#define N 5
int main()
{int i, length, len;char *str[N] = { "C/C++", "computer", "programming", "pragma", "once" };char *maxLenStr;length = 0;for( i=0; iif( ( len = strlen( str[i] ) ) > length ){length = len;maxLenStr = str[i];}}printf( "最长字符串是:%s, 其长度为:%d\n", maxLenStr, length );return 0;
}

运行结果:
在这里插入图片描述
说明:在第7行代码,字符串数组中的每个元素均是字符串常量,将其赋值给左端的指针数组,在不同C语言编译器中对其处理的结果是相同的,但是会出现告警信息:将字符串常量赋值为字符指针变量。这是由指针数组中的元素没有进行初始化导致的。

——————————————————————
未完待续!

相关内容

热门资讯

银河麒麟V10SP1高级服务器... 银河麒麟高级服务器操作系统简介: 银河麒麟高级服务器操作系统V10是针对企业级关键业务...
【NI Multisim 14...   目录 序言 一、工具栏 🍊1.“标准”工具栏 🍊 2.视图工具...
AWSECS:访问外部网络时出... 如果您在AWS ECS中部署了应用程序,并且该应用程序需要访问外部网络,但是无法正常访问,可能是因为...
不能访问光猫的的管理页面 光猫是现代家庭宽带网络的重要组成部分,它可以提供高速稳定的网络连接。但是,有时候我们会遇到不能访问光...
AWSElasticBeans... 在Dockerfile中手动配置nginx反向代理。例如,在Dockerfile中添加以下代码:FR...
Android|无法访问或保存... 这个问题可能是由于权限设置不正确导致的。您需要在应用程序清单文件中添加以下代码来请求适当的权限:此外...
月入8000+的steam搬砖... 大家好,我是阿阳 今天要给大家介绍的是 steam 游戏搬砖项目,目前...
​ToDesk 远程工具安装及... 目录 前言 ToDesk 优势 ToDesk 下载安装 ToDesk 功能展示 文件传输 设备链接 ...
北信源内网安全管理卸载 北信源内网安全管理是一款网络安全管理软件,主要用于保护内网安全。在日常使用过程中,卸载该软件是一种常...
AWS管理控制台菜单和权限 要在AWS管理控制台中创建菜单和权限,您可以使用AWS Identity and Access Ma...