【C语言】高级指针话题 {一种很好的理解声明的方式}

本文为学习《C和指针》的笔记之一

高级声明

int * f ( )

优先级:()> *

首先执行的是函数调用操作符号 ( )

因此 f 是一个函数

它的返回值类型是一个指向整型的指针

对 f 使用()函数调用 后 ,对返回值进行 间接访问 后得到 int

int ( * f )( )

第1个括号起到聚组的作用 : 迫使间接访问在函数调用之前进行

第2对括号是函数调用操作符

结果 f 成为了一个函数指针

它指向的函数返回一个整型值

对 f 进行间接访问 后 使用()函数调用,最终得到 int

int *( * f )( )

f是一个函数指针

指向一个返回值为整型指针的函数

*对 f 进行间接访问后 使用 () 函数调用用后 再使用间接访问后得到 int *

int f( )[ ]

这个声明是非法的

f是一个函数 返回值是一个整型数组

对 f 进行 ()函数调用后 使用 [ ] 下标引用 后得到 int

int f [ ] ( )

非法声明

f 似乎是一个数组

它的元素为返回值为int 的函数

数组要求元素必须有相同的函数,而这些函数显然可能有不同的长度

对 f 进行 [ ] 下标引用后 ,使用()函数调用 得到返回值 为int

int (*f[ ])( )

优先级:[ ] > *

f 是一个数组

数组元素的类型数函数指针

函数指针指向的函数的返回值是int

*对 f 进行下标引用后 再对其进行 间接访问 后 使用()函数调用 得到返回值为int *

—以上都是旧式风格的声明,未标明函数参数的类型—

int (*f)( int , float)

f是一个函数指针

它所指的函数接受两个参数,分别是 int 和 float

int *(*g[ ])(int,float)

g是一个数组

数组的元素类型是函数指针

它所指向的函数接受两个参数,分别是 int 和 float

程序cdecl可以将声明解释,自行搜索获取

函数指针

用武之处比较少

一般只用转换表和作为参数传递给另一个函数

警告:简单声明一个函数指针不代表它立刻能使用,必须有初始化

int f(int);
//函数指针的声明与初始化
int (*pf)(int) = &f;

//三种调用函数的方法
int ans;
ans = f(25);
ans = (*pf)(25);			//直接将函数取出后调用
ans = pf(25);				//编译器看到函数指针(知道函数地址)就可以对函数进行调用

回调函数

将函数1作为参数传入函数2

函数2再运行时将回调函数1

意义

使所编写的函数能够再不同的时刻执行不同类型的工作

例子

一个再链表中查找数据的函数

返回链接

#include<stdio.h>
#include<string>
//再传递参数时,常使用指针,以尽量缩小函数的空间与时间
 /*注意必要的强制类型转换:比较函数的参数必须被声明未void*以匹配查找函数的原型,然后它们再强制转换为int*类型,用于比较整型值*/
//查找int类型
int compare_ints(void const *a,void const *b)
{
	if(*(int *)a == *(int *)b )

        return 0;
    else
        return 1;
}

/*查找字符串类型的时候可以直接使用标准库函数strcmp传入(不过它的参数被声明为char
*可能会引起警告)*/

//node是一个链表空间单元的类型
Node * search_list(Node *node,void const *value,int (*compare)(void const *,void const*))
{
    while(node != NULL)
    {
        if (compare(&node->value,value)==0)
            break;
        node = node->link;
	}
    return node
}


desired = search_list(pNode1,25,com,compare_ints)//再整型链表中查找
desired = sreach_list(pNode1,"Jhon",strcmp)//再字符串链表中查找

转移表

指的是一个函数指针数组

再不同下标引用时进行不同的操作

Ep:

一个小小的计算器中的组件

double add(double,double);
double sub(double,double);
double mul(double,double);
double div(double,double);
.....
//构成转换表
double (*oper_func[])(double,double)={add,sub,mul,div,...}
//使用
result = oper_func[oper](op1,op2)

警告:在转换表中出现越界错误是可怕的,系统难以找到出错的根源,若执行中不出错但结果错误,那么会修改机器如何到达错误最后发生地点的线索

所以一开始就要对下标进行检查

保证不会出错

或在转换表中函数追加检测是否执行了函数的步骤

命令行参数

传递命令行参数

c程序的main函数具有两个形参(有些操作系统是三个)

第一个是argc,表示命令行参数的个数

第二个是aegv,指向一组参数值(第一个元素的首地址),这些元素每一个都是指向一个参数文本的指针

argc和argv是习惯常用参数名,也可另取名

//可以移动指针数组内char*指针来访问参数
void main(int argc,char*argv[])//更安全,便于多次访问命令行参数
    //或
void main(int argc,char**argv)//更灵活一些,可以移动argv指针
argv[0]指向程序本身" .exe "(在以不同名字启动程序时可能有不同效果)
argv[1]指向命令行参数第一个字数串常数
argv[2]指向命令行参数第二个字数串常数

Ep:

$cc -c -o main.c insert.c -o -test
argv->‘c’'c’0
‘-’'c’0
‘m’‘a’‘i’‘n’'.'c’0
‘i’‘n’‘s’‘e’‘r’‘t’‘.’'c’0
‘-’'o’0
‘t’‘e’‘s’'t’0
0
argc7

参数以空格分隔

处理命令行参数

一般把选项参数以 - 开头

把文件名参数 直接传入

检查 - 后选项

再检测 文件参数(如果为空,则可以调用输入函数)

甚至 你可以在一个参数内放入多个选项字母

$ prog -abc name1 name2 name3

int option_a,.....
while(*++argv != NULL && **argv =='-')
{
    while ((opt)=*++*argv!='\0')
	{
		switch(opt)
		{
		case 'a':
			option_a = TRUE;
			break;
		.....
		}
	}
}
//使用后argv移动到了第一个不是 - 开头的参数

注意,使用以上程序时,命令行参数可能只处理一次,因为argv指针及其内部指针都被改动了位置

并且,选项可能是一个单词而不是一个字母,或者有可能与某些选项联系在一起

字符串常量

当它出现在表达式中时,它的值是一个指针常量

“xyz” + 1

结果是个指针

指向字符串中的第二个字符:y

*“xyz”

对指针进行间接访问操作

结果是char型字符 ‘x’

“xyz”[2]

结果是char型字符’z’

“xyz”[4]

是一个不可预测的字符

作用

如区间段数据可视化

或者转换输出八进制,十六进制时

putchar("0123456789ABCDEF"[value%16]);
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值