[c语言]深入返回值为函数指针的函数

之前写过个好玩代码
c语言返回值为函数指针的函数

一、发现

#include<stdio.h>

int (*drink(void)) (void)
{
    static int i;
    i++;
    printf("(%d)\n", i);
    return (int(*)(void))drink;
}

int main()
{
    drink()();
    return 0;
}

这个代码定义了一个返回值为函数指针的函数,然后就能直接调用两次函数,但这种方法对于调用三次函数来说好像不太可能。
后来我想一想,好像可以先定义一个函数指针类型,然后这样函数的定义也稍微简介一些

#include <stdio.h>

typedef long long (*p_fun)(void);

p_fun fun()
{
    printf("()");
    return fun;
}

int main()
{
    fun()();
    return 0;
}

运行结果:
在这里插入图片描述

二、探索

然后我又仔细想了想,是不是可以套娃,然后就有了下面的代码

#include <stdio.h>

typedef long long (*p_fun)(void);
typedef p_fun (*p_fun2)(void);

p_fun2 fun()
{
    printf("()");
    return fun;
}

int main()
{
    fun()()();
    return 0;
}
#include <stdio.h>

typedef long long (*p_fun)(void);
typedef p_fun (*p_fun2)(void);
typedef p_fun2 (*p_fun3)(void);

p_fun3 fun()
{
    printf("()");
    return fun;
}

int main()
{
    fun()()()();
    return 0;
}

运行结果:
在这里插入图片描述

然后我们可以一直定义函数指针类型,就可以一直循环操作下去,最终可以实现比较难懂的代码

#include <stdio.h>

typedef long long (*p_fun)(void);
typedef p_fun (*p_fun2)(void);
typedef p_fun2 (*p_fun3)(void);
typedef p_fun3 (*p_fun4)(void);
typedef p_fun4 (*p_fun5)(void);
typedef p_fun5 (*p_fun6)(void);
typedef p_fun6 (*p_fun7)(void);
typedef p_fun7 (*p_fun8)(void);
typedef p_fun8 (*p_fun9)(void);
typedef p_fun9 (*p_fun10)(void);
typedef p_fun10 (*p_fun11)(void);
typedef p_fun11 (*p_fun12)(void);
typedef p_fun12 (*p_fun13)(void);
typedef p_fun13 (*p_fun14)(void);
typedef p_fun14 (*p_fun15)(void);
typedef p_fun15 (*p_fun16)(void);
typedef p_fun16 (*p_fun17)(void);
typedef p_fun17 (*p_fun18)(void);
typedef p_fun18 (*p_fun19)(void);
typedef p_fun19 (*p_fun20)(void);
typedef p_fun20 (*p_fun21)(void);
typedef p_fun21 (*p_fun22)(void);

p_fun22 fun()
{
    printf("()");
    return fun;
}

int main()
{
    fun()()()()()()()()()()()()()()()()()()()()()()();
    return 0;
}

运行结果:
在这里插入图片描述

三、深究

其实用gcc这样编译会报warning
warning: returning ‘long long int (* (* (* (* (* (* (* (* (* (* (* (* (* (* (* (* (* (* (* (* (* (* (* ()())())(void))(void))(void))(void))(void))(void))(void))(void))(void))(void))(void))(void))(void))(void))(void))(void))(void))(void))(void))(void))(void))(void)’ from a function with incompatible return type ‘a’ {aka 'long long int ( (* (* (* (* (* (* (* (* (* (* (* (* (* (* (* (* (* (* (* (* (* (*)())(void))(void))(void))(void))(void))(void))(void))(void))(void))(void))(void))(void))(void))(void))(void))(void))(void))(void))(void))(void))(void))(void)’} [-Wincompatible-pointer-types]
return fun;
然后我们能看到一个比较复杂的类型,我们再次根据这个类型进行定义
这是原始类型

long long int (* (* (* (* (* (* (* (* (* (* (* (* (* (* (* (* (* (* (* (* (* (* (*)())(void))(void))(void))(void))(void))(void))(void))(void))(void))(void))(void))(void))(void))(void))(void))(void))(void))(void))(void))(void))(void))(void);

这是我们把这个类型重命名为a

typedef long long int (* (* (* (* (* (* (* (* (* (* (* (* (* (* (* (* (* (* (* (* (* (* (*a)())(void))(void))(void))(void))(void))(void))(void))(void))(void))(void))(void))(void))(void))(void))(void))(void))(void))(void))(void))(void))(void))(void);

接下来重新写一下代码

#include <stdio.h>

typedef long long int (* (* (* (* (* (* (* (* (* (* (* (* (* (* (* (* (* (* (* (* (* (* (*a)())(void))(void))(void))(void))(void))(void))(void))(void))(void))(void))(void))(void))(void))(void))(void))(void))(void))(void))(void))(void))(void))(void);

a fun()
{
    printf("()");
    return fun;
}

int main()
{
    fun()()()()()()()()()()()()()()()()()()()()()()();
    return 0;
}

发现还是能用,聪明的你能说出他的类型名吗?

其实我们可以更疯狂一点:

#include <stdio.h>

typedef long long (*p_fun0)(void);
typedef p_fun0 (*p_fun1)(void);
typedef p_fun1 (*p_fun2)(void);
typedef p_fun2 (*p_fun3)(void);
typedef p_fun3 (*p_fun4)(void);
typedef p_fun4 (*p_fun5)(void);
typedef p_fun5 (*p_fun6)(void);
typedef p_fun6 (*p_fun7)(void);
typedef p_fun7 (*p_fun8)(void);
typedef p_fun8 (*p_fun9)(void);
typedef p_fun9 (*p_fun10)(void);
typedef p_fun10 (*p_fun11)(void);
typedef p_fun11 (*p_fun12)(void);
typedef p_fun12 (*p_fun13)(void);
typedef p_fun13 (*p_fun14)(void);
typedef p_fun14 (*p_fun15)(void);
typedef p_fun15 (*p_fun16)(void);
typedef p_fun16 (*p_fun17)(void);
typedef p_fun17 (*p_fun18)(void);
typedef p_fun18 (*p_fun19)(void);
typedef p_fun19 (*p_fun20)(void);
typedef p_fun20 (*p_fun21)(void);
typedef p_fun21 (*p_fun22)(void);
typedef p_fun22 (*p_fun23)(void);
typedef p_fun23 (*p_fun24)(void);
typedef p_fun24 (*p_fun25)(void);
typedef p_fun25 (*p_fun26)(void);
typedef p_fun26 (*p_fun27)(void);
typedef p_fun27 (*p_fun28)(void);
typedef p_fun28 (*p_fun29)(void);
typedef p_fun29 (*p_fun30)(void);
typedef p_fun30 (*p_fun31)(void);
typedef p_fun31 (*p_fun32)(void);
typedef p_fun32 (*p_fun33)(void);
typedef p_fun33 (*p_fun34)(void);
typedef p_fun34 (*p_fun35)(void);
typedef p_fun35 (*p_fun36)(void);
typedef p_fun36 (*p_fun37)(void);
typedef p_fun37 (*p_fun38)(void);
typedef p_fun38 (*p_fun39)(void);
typedef p_fun39 (*p_fun40)(void);
typedef p_fun40 (*p_fun41)(void);
typedef p_fun41 (*p_fun42)(void);
typedef p_fun42 (*p_fun43)(void);
typedef p_fun43 (*p_fun44)(void);
typedef p_fun44 (*p_fun45)(void);
typedef p_fun45 (*p_fun46)(void);
typedef p_fun46 (*p_fun47)(void);
typedef p_fun47 (*p_fun48)(void);
typedef p_fun48 (*p_fun49)(void);
typedef p_fun49 (*p_fun50)(void);
typedef p_fun50 (*p_fun51)(void);
typedef p_fun51 (*p_fun52)(void);
typedef p_fun52 (*p_fun53)(void);
typedef p_fun53 (*p_fun54)(void);
typedef p_fun54 (*p_fun55)(void);
typedef p_fun55 (*p_fun56)(void);
typedef p_fun56 (*p_fun57)(void);
typedef p_fun57 (*p_fun58)(void);
typedef p_fun58 (*p_fun59)(void);
typedef p_fun59 (*p_fun60)(void);
typedef p_fun60 (*p_fun61)(void);
typedef p_fun61 (*p_fun62)(void);
typedef p_fun62 (*p_fun63)(void);
typedef p_fun63 (*p_fun64)(void);
typedef p_fun64 (*p_fun65)(void);
typedef p_fun65 (*p_fun66)(void);
typedef p_fun66 (*p_fun67)(void);
typedef p_fun67 (*p_fun68)(void);
typedef p_fun68 (*p_fun69)(void);
typedef p_fun69 (*p_fun70)(void);
typedef p_fun70 (*p_fun71)(void);
typedef p_fun71 (*p_fun72)(void);
typedef p_fun72 (*p_fun73)(void);
typedef p_fun73 (*p_fun74)(void);
typedef p_fun74 (*p_fun75)(void);
typedef p_fun75 (*p_fun76)(void);
typedef p_fun76 (*p_fun77)(void);
typedef p_fun77 (*p_fun78)(void);
typedef p_fun78 (*p_fun79)(void);
typedef p_fun79 (*p_fun80)(void);
typedef p_fun80 (*p_fun81)(void);
typedef p_fun81 (*p_fun82)(void);
typedef p_fun82 (*p_fun83)(void);
typedef p_fun83 (*p_fun84)(void);
typedef p_fun84 (*p_fun85)(void);
typedef p_fun85 (*p_fun86)(void);
typedef p_fun86 (*p_fun87)(void);
typedef p_fun87 (*p_fun88)(void);
typedef p_fun88 (*p_fun89)(void);
typedef p_fun89 (*p_fun90)(void);
typedef p_fun90 (*p_fun91)(void);
typedef p_fun91 (*p_fun92)(void);
typedef p_fun92 (*p_fun93)(void);
typedef p_fun93 (*p_fun94)(void);
typedef p_fun94 (*p_fun95)(void);
typedef p_fun95 (*p_fun96)(void);
typedef p_fun96 (*p_fun97)(void);
typedef p_fun97 (*p_fun98)(void);
typedef p_fun98 (*p_fun99)(void);
typedef p_fun99 (*p_fun100)(void);

p_fun100 fun()
{
    printf("()");
    return fun;
}

int main()
{
    fun()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()();
    return 0;
}

或者

#include <stdio.h>

typedef long long int (* (* (* (* (* (* (* (* (* (* (* (* (* (* (* (* (* (* (* (* (* (* (* (* (* (* (* (* (* (* (* (* (* (* (* (* (* (* (* (* (* (* (* (* (* (* (* (* (* (* (* (* (* (* (* (* (* (* (* (* (* (* (* (* (* (* (* (* (* (* (* (* (* (* (* (* (* (* (* (* (* (* (* (* (* (* (* (* (* (* (* (* (* (* (* (* (* (* (* (* (* (*a)())(void))(void))(void))(void))(void))(void))(void))(void))(void))(void))(void))(void))(void))(void))(void))(void))(void))(void))(void))(void))(void))(void))(void))(void))(void))(void))(void))(void))(void))(void))(void))(void))(void))(void))(void))(void))(void))(void))(void))(void))(void))(void))(void))(void))(void))(void))(void))(void))(void))(void))(void))(void))(void))(void))(void))(void))(void))(void))(void))(void))(void))(void))(void))(void))(void))(void))(void))(void))(void))(void))(void))(void))(void))(void))(void))(void))(void))(void))(void))(void))(void))(void))(void))(void))(void))(void))(void))(void))(void))(void))(void))(void))(void))(void))(void))(void))(void))(void))(void))(void))(void);

a fun()
{
    printf("()");
    return fun;
}

int main()
{
    fun()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()();
    return 0;
}

运行结果
或者我们可以在fun()函数里面加点私货,就可以看到我们调用过多少次函数
在这里插入图片描述

四、复用

这么多的代码难道你以为我是自己写的???
还记得博主之前自己用c语言写c语言代码的博客吗?
[C语言]关于我用C语言写C语言代码
所以我自己又写了一个c语言来帮我写c语言代码
下面是参考代码

#include <stdio.h>
#define M 99

int main()
{
    int i;
    printf("#include <stdio.h>\n\n");

    printf("typedef long long (*p_fun0)(void);\n");
    for(i = 0 ; i <= M ; ++i)
    {
        printf("typedef p_fun%d (*p_fun%d)(void);\n", i, i+1);
    }

    printf("\np_fun%d fun()\n{\n", i);
    printf("    printf(\"()\");\n");
    printf("    return fun;\n}\n\n");

    printf("int main()\n{\n");
    printf("    fun()");
    for(i = 1 ; i <= M + 2 ; ++i)
    {
        printf("()");   
    }
    printf(";\n");
    printf("    return 0;\n}\n");
    return 0;
}

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

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

相关文章

Kafka-Java一:Spring实现kafka消息的简单发送

目录 写在前面 一、创建maven项目 二、引入依赖 2.1、maven项目创建完成后&#xff0c;需要引入以下依赖 2.2、创建工程目录 三、创建生产者 3.1、创建生产者&#xff0c;同步发送消息 3.2、创建生产者&#xff0c;异步发送消息 四、同步发送消息和异步发送消息的区别…

【计算机毕设案例推荐】高校学术研讨信息管理系统小程序SpringBoot+Vue+小程序

前言&#xff1a;我是IT源码社&#xff0c;从事计算机开发行业数年&#xff0c;专注Java领域&#xff0c;专业提供程序设计开发、源码分享、技术指导讲解、定制和毕业设计服务 项目名 基于SpringBoot的高校学术研讨信息管理系统小程序 技术栈 SpringBoot小程序VueMySQLMaven 文…

reqable(小黄鸟)+雷电抓包安卓APP

x 下载证书保存到雷电模拟器根目录(安装位置) 为什么? Android7以上&#xff0c;系统允许每个应用可以定义自己的可信CA集&#xff0c;部分的应用默认只会信任系统预装的CA证书&#xff0c;而不会信任用户安装的证书&#xff0c;之前的方法安装Burp/Fiddler证书都是用户证书…

sklearn-6算法链与管道

思想类似于pipeline&#xff0c;将多个处理步骤连接起来。 看个例子&#xff0c;如果用MinMaxScaler和训练模型&#xff0c;需要反复执行fit和tranform方法&#xff0c;很繁琐&#xff0c;然后还要网格搜索&#xff0c;交叉验证 1 预处理进行参数选择 对于放缩的数据&#x…

谢谢大家!

注&#xff1a;此篇都是真心话&#xff01; 谢谢各位对我长久以来的支持&#xff0c;感谢感谢&#xff01; 感谢各位把我的阅读量提升到21487&#xff01; 感谢各位把我的排名提升到24916&#xff08;灰长前&#xff0c;干到前1000我发超长文章&#xff09;&#xff01; 感谢…

大数据调度最佳实践 | 从Airflow迁移到Apache DolphinScheduler

迁移背景 有部分用户原来是使用 Airflow 作为调度系统的&#xff0c;但是由于 Airflow 只能通过代码来定义工作流&#xff0c;并且没有对资源、项目的粒度划分&#xff0c;导致在部分需要较强权限控制的场景下不能很好的贴合客户需求&#xff0c;所以部分用户需要将调度系统从…

《动手学深度学习 Pytorch版》 9.7 序列到序列学习(seq2seq)

循环神经网络编码器使用长度可变的序列作为输入&#xff0c;将其编码到循环神经网络编码器固定形状的隐状态中。 为了连续生成输出序列的词元&#xff0c;独立的循环神经网络解码器是基于输入序列的编码信息和输出序列已经看见的或者生成的词元来预测下一个词元。 要点&#x…

重测序基因组:Pi核酸多样性计算

如何计算核酸多样性 Pi 本期笔记分享关于核酸多样性pi计算的方法和相关技巧&#xff0c;主要包括原始数据整理、分组文件设置、计算原理、操作流程、可视化绘图等步骤。 基因组Pi核酸多样性&#xff08;Pi nucleic acid diversity&#xff09;是一种遗传学研究中用来描述种群内…

H5前端开发——BOM

H5前端开发——BOM BOM&#xff08;Browser Object Model&#xff09;是指浏览器对象模型&#xff0c;它提供了一组对象和方法&#xff0c;用于与浏览器窗口进行交互。 通过 BOM 对象&#xff0c;开发人员可以操作浏览器窗口的行为和状态&#xff0c;实现与用户的交互和数据传…

设计模式之命令模式

文章目录 一、介绍二、命令模式中的角色三、案例1. 命令的抽象接口Command2. 进攻AttackCommand3. 意大利炮cannonCommand4. 开炮FireCommand5. 李云龙LiYunLong6. 运行案例 四、优缺点 一、介绍 命令模式(Command Pattern)&#xff0c;属于行为型设计模式。指的是把方法调用封…

系统架构设计师之RUP软件开发生命周期

系统架构设计师之RUP软件开发生命周期

自建的离散傅里叶变换matlab程序实现及其与matlab自带函数比较举例

自建的离散傅里叶变换matlab程序实现及其与matlab自带函数比较举例 在matlab中有自带的离散傅里叶变换程序&#xff0c;即fft程序&#xff0c;但该程序是封装的&#xff0c;无法看到源码。为了比较清楚的了解matlab自带的实现过程&#xff0c;本文通过自建程序实现matlab程序&…

IntelliJ IDEA 2023.2正式发布,新UI和Profiler转正

你好&#xff0c;我是YourBatman&#xff1a;做爱做之事❣交配交之人。 &#x1f4da;前言 北京时间2023年7月26日&#xff0c;IntelliJ IDEA 2023.2正式发布。老规矩&#xff0c;吃肉之前&#xff0c;可以先把这几碗汤干了&#xff0c;更有助于消化&#xff08;每篇都很顶哦…

排序-表排序

当我们需要对一个很大的结构体进行排序时&#xff0c;因为正常的排序需要大量的交换&#xff0c;这就会造成时间复杂度的浪费 因此&#xff0c;我们引入指针&#xff0c;通过指针临时变量的方式来避免时间复杂度的浪费 间接排序-排序思路&#xff1a;通过开辟一个指针数组&…

十个最常用的计算机视觉数据集

如今&#xff0c;人工智能和机器学习领域中最振奋人心的一个分支是计算机视觉&#xff08;Computer Vision&#xff0c;简称CV&#xff09;。CV应用于多种场景&#xff0c;以改善我们的日常生活&#xff0c;并推进科学技术研究。其中包括&#xff1a; 自动驾驶自动生成图像描述…

重入漏洞EtherStore

重入漏洞 // SPDX-License-Identifier: MIT pragma solidity ^0.8.13;contract EtherStore {mapping(address > uint) public balances;function deposit() public payable {balances[msg.sender] msg.value;}function withdraw() public {uint bal balances[msg.sender]…

Linux 函数调用的用户态与内核态

在用户态中&#xff0c;程序的执行往往是一个函数调用另一个函数。函数调用都是通过栈来进行的。 在进程的内存空间里面&#xff0c;栈是一个从高地址到低地址&#xff0c;往下增长的结构&#xff0c;也就是上面是栈底&#xff0c;下面是栈顶&#xff0c;入栈和出栈的操作都是…

ModbusTCP 转 Profinet 主站网关在博图配置案例

兴达易控ModbusTCP转Profinet网关&#xff0c;在 Profinet 侧做为 Profinet 主站控制器&#xff0c;接 Profinet 设备&#xff0c;如伺服驱动器&#xff1b;兴达易控ModbusTCP 和 Profinet网关在 ModbusTCP 侧做为 ModbusTCP 从站&#xff0c;接 PLC、上位机、wincc 屏等。 拓…

k8s kubeadm配置

master 192.168.41.30 docker、kubeadm、kubelet、kubectl、flannel node01 192.168.41.31 docker、kubeadm、kubelet、kubectl、flannel node02 192.168.41.32 do…

python 字典dict和列表list的读取速度问题, range合并

嗨喽&#xff0c;大家好呀~这里是爱看美女的茜茜呐 python 字典和列表的读取速度问题 最近在进行基因组数据处理的时候&#xff0c;需要读取较大数据&#xff08;2.7G&#xff09;存入字典中&#xff0c; 然后对被处理数据进行字典key值的匹配&#xff0c;在被处理文件中每次…