重庆分公司,新征程启航
为企业提供网站建设、域名注册、服务器等服务
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语言编译器中对其处理的结果是相同的,但是会出现告警信息:将字符串常量赋值为字符指针变量。这是由指针数组中的元素没有进行初始化导致的。
——————————————————————
未完待续!
你是否还在寻找稳定的海外服务器提供商?创新互联www.cdcxhl.cn海外机房具备T级流量清洗系统配攻击溯源,准确流量调度确保服务器高可用性,企业级服务器适合批量采购,新人活动首月15元起,快前往官网查看详情吧