C语言指针的奇妙用法

14 篇文章 1 订阅

C语言的指针也算是一大特色了,C语言一方面有一套完整的语法规则,变量必须明确声明,常量、变量、字面量都要区分,函数返回值要与声明一致等,另一方面,C语言又给予开发者很大的自由,甚至数组不会检查越界,比较自由的是指针可以指向任意数据类型,可以指向结构和函数。指针这个东西发挥空间是很大的。有意思的是指向void的指针可以转换为指向任意类型的指针,这个规则是很好用的。下面是我发现的几个有意思的指针用法。

返回值为指向函数的指针的函数

一个函数指针作为另一个函数的参数不稀奇,但一个函数的返回值为一个函数指针感觉还是很少见的。
我的做法是:

#include<stdio.h>

int fun1(int);//基本的函数
int fun2(int(*)(int),int);//函数指针作为参数
void* fun3(int);//返回一个指向void的指针,这个指针可以指向任意类型,我们可以让它返回一个函数指针
void* fun4(int(*)(int),int);//既有函数指针作为参数,又可以返回一个函数指针
//如果想返回一个函数指针的话,问题是没法限定返回指针指向的函数类型,C语言中还是会区分函数和数据类型的
int main(void){
    printf("fun1(1)=%d\n",fun1(1));
    printf("fun2(fun1,1)=%d\n",fun2(fun1,1));
    int (*rf)(int)=fun3(1);
    printf("fun3(1)(1)=%d\n",rf(1));
    int (*rf1)(int)=fun4(fun1,1);
    printf("fun4(fun1,1)(1)=%d\n",rf1(1));

    return 0;
}
int fun1(int i){
    static int times=0;
    times++;
    printf("fun1 is running, times= %d\n",times);
    return times+i;
}
int fun2(int(*f)(int), int i){
    printf("fun2 is running\n");
    return f(1);
}
void* fun3(int i){
    printf("fun3 is running\n");
    return fun1;
}
void* fun4(int(*f)(int),int i){
    printf("fun4 is running\n");
    return fun1;
}
fun1 is running, times= 1
fun1(1)=2
fun2 is running
fun1 is running, times= 2
fun2(fun1,1)=3
fun3 is running
fun1 is running, times= 3
fun3(1)(1)=4
fun4 is running
fun1 is running, times= 4
fun4(fun1,1)(1)=5

其中第一个函数一共调用了4次。

利用函数对一个结构进行包装

C语言毕竟不是面向对象的语言,它没有class。C语言的结构也很简单,只能声明这个结构拥有那些数据类型以及这个数据类型的名字,它也没有构造器,只能我们自己在新建结构的对象时对其中的变量初始化。结构中也不能定义函数,但我们可以将某种类型的函数指针作为成员,利用这一点我们似乎可以做一些有意思的事情。
可以用一个函数接受一些参数,创建并初始化某个结构对象,然后返回它,结构中可以包含某种类型的函数指针,这个成员可以在后面绑定特定类型的函数。但没法像C++那样,一个类中的成员函数可以直接访问类中的数据,所以C语言中要用结构中的函数指针指向的函数时,要访问结构中的数据必须把结构对象作为参数传给函数。虽然麻烦点,但确实是可以的。
如下

#include<stdio.h>
#include<string.h>
#include<stdlib.h>
typedef struct stt{
    struct stt* this; //要用struct st,不能用重定义的名字
    char name[20];
    int age;
    char phone[15];
    char strs[50];//不能返回一个局部变量的地址,意味着不能直接返回一个字符串,还是以字符串的形式
    int(*getAge)(struct stt*);//结构中可以有函数指针
}strf;
char* tostringss(strf*,char*);
//char* tos();
int getAge(strf*);
strf strf_init(char*,int,char*);//相当于构造器
int main(void){
    strf st=strf_init("xie",24,"17051145259");
    printf("%s\n",st.strs);
    printf("st.age=%d\n",st.getAge(&st));
    return 0;
}
char* tostringss(strf* s,char*str){
    strcpy(str,s->name);
    strcat(str,", ");
    char ages[4];
    int a=s->age,ti=0;
    if(a>9){
        ages[0]=a/10+'0';
        ages[1]=a%10+'0';
    }else
        ages[0]=a+'0';
    ages[2]='\0';
    strcat(str,ages);
    strcat(str,", ");
    strcat(str,s->phone);
    return str;
}
int getAge(strf* s){
    return s->age;
}
strf strf_init(char* name,int age,char* phone){
    strf st={.age=age};
    strcpy(st.name,name);
    strcpy(st.phone,phone);
    st.this=&st;
    char ch[50];
    strcpy(st.strs,tostringss(&st,ch));
    st.getAge=getAge;
    return st; //不能返回局部变量的地址
}
xhh@DESKTOP-624LRQ5:/mnt/d/Program Files/code/algo_learn/c_algo$ ./strucf
xie, 24, 17051145259
st.age=24

但其实尝试的时候就会发现,它能做的事情是很有限的,(可能总能想办法解决,毕竟C语言,但很费劲),还是存在很多限制。很多事情虽然费点功夫总能办到,但这样开发效率就完全不如很多别的语言了,所以这些都仅供娱乐。
顺便说一下,可惜C语言中没有匿名函数,不限麻烦的话感觉也可以用C语言进行函数式编程。

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值