热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

用C语言模仿Python函数

首先得说明一点,C语言不是函数式编程语言,要想进行完全的函数式编程,还得先写个虚拟机,然后再写个解释器才行(相当于CPython)。下面我们提供一个例子,说明即便不写虚拟机,C语言函数也是可

首先得说明一点,C 语言不是函数式编程语言,要想进行完全的函数式编程,还得先写个虚拟机,然后再写个解释器才行(相当于 CPython )。

下面我们提供一个例子,说明即便不写虚拟机, C 语言函数也是可以“适度地模仿” Python 函数。

我们有如下的 Python 程序:

1 def line_conf(a, b):
2 def line(x):
3 return a*x + b
4 return line
5
6 line1 = line_conf(1, 1)
7 line2 = line_conf(4, 5)
8 print(line1(5), line2(5))
Python Code

 

我们在C程序中适度地模拟其中的line_conf函数:

  1 /* MIT License
2
3 Copyright (c) 2017 Yuandong-Chen
4
5 Permission is hereby granted, free of charge, to any person obtaining a copy
6 of this software and associated documentation files (the "Software"), to deal
7 in the Software without restriction, including without limitation the rights
8 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 copies of the Software, and to permit persons to whom the Software is
10 furnished to do so, subject to the following conditions:
11
12 The above copyright notice and this permission notice shall be included in all
13 copies or substantial portions of the Software.
14
15 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 SOFTWARE. */
22
23 ///////////////////////////////////////////////////////////////////////////////
24
25 // Note: The C program is almost equivalent to the Python program as follows:
26 // def line_conf(a, b):
27 // def line(x):
28 // return a*x + b
29 // return line
30 //
31 // line1 = line_conf(1, 1)
32 // line2 = line_conf(4, 5)
33 // print(line1(5), line2(5))
34
35 #include
36 #include
37 #include
38 #include
39
40 typedef int Func();
41
42 Func *line_conf(int x, int y,...)
43 {
44 va_list ap;
45 va_start(ap, y);
46
47 asm volatile(
48 "push %%eax\n\t"
49 "subl $40, %%esp\n\t"
50 "movl 8(%%ebp), %%eax\n\t"
51 "movl %%eax, -36(%%ebp)\n\t"
52 "movl 12(%%ebp), %%eax\n\t"
53 "movl %%eax, -40(%%ebp)\n\t"
54 "addl $40, %%esp\n\t"
55 "pop %%eax\n\t"
56 :::"memory"
57 );
58
59 if(va_arg(ap,int) == 1){
60
61 LINE:
62
63 asm volatile(
64 "push %%ebp\n\t"
65 "movl %%esp, %%ebp\n\t"
66 "movl 8(%%ebp), %%eax\n\t"
67 "imul -36(%%ebp), %%eax\n\t"
68 "addl -40(%%ebp), %%eax\n\t"
69 "movl %%ebp, %%esp\n\t"
70 "pop %%ebp\n\t"
71 "ret\n\t"
72 :::"memory","%eax"
73 );
74 }
75 __END:
76 va_end(ap);
77 return (Func *)(&&LINE);
78 }
79
80 int main(int argc, const char *argv[]){
81 printf("====TEST START====\n");
82 printf("34*234+6 ?= %d\n",line_conf(34,6)(234));
83 printf("1*3+2 ?= %d; 324*65+3 ?= %d; 13*66+2 ?= %d\n",line_conf(1,2)(3),line_conf(324,3)(65),line_conf(13,2)(66));
84
85 int fd = line_conf(1,6)(4);
86 Func *fun = line_conf(3,3);
87 int a = 1; // Limited point
88 printf("3*3+3 ?= %d; 1*4+6 ?= %d\n",fun(3),fd);
89 printf("====TEST END====\n");
90 return 0;
91 }
92
93 // Compile it by the following command:
94 // gcc -m32 -O0 -fno-stack-protector CFunctional.c; ./a.out
95 // The terminal output should looks like:
96 // ====TEST START====
97 // 34*234+6 ?= 7962
98 // 1*3+2 ?= 5; 324*65+3 ?= 21063; 13*66+2 ?= 860
99 // 3*3+3 ?= 12; 1*4+6 ?= 10
100 // ====TEST END====
101 //Note: The limitation happens between line 86 and line 88, we cannot insert any function here
102 // whose stack is larger than 40 bytes.(Why is 40? check the inline assembler language)
C Code

结果在MacOSX和Ubuntu上(i386)都能通过简单的测试。但是可以看到,仅仅是简单的模拟,我们也得用到大量(按比例)的汇编,可读性很差,而且模拟程度非常有限,代码长度也更长。

注意:这只是个玩具,别这么写代码,除非想搞破坏(充斥着各种漏洞,极易被侵入)。


推荐阅读
  • 本文节选自《NLTK基础教程——用NLTK和Python库构建机器学习应用》一书的第1章第1.2节,作者Nitin Hardeniya。本文将带领读者快速了解Python的基础知识,为后续的机器学习应用打下坚实的基础。 ... [详细]
  • iOS 不定参数 详解 ... [详细]
  • 【妙】bug称它为数组越界的妙用
    1、聊一聊首先跟大家推荐一首非常温柔的歌曲,跑步的常听。本文主要把自己对C语言中柔性数组、零数组等等的理解分享给大家,并聊聊如何构建一种统一化的学习思想 ... [详细]
  • IOS Run loop详解
    为什么80%的码农都做不了架构师?转自http:blog.csdn.netztp800201articledetails9240913感谢作者分享Objecti ... [详细]
  • 微服务优雅上下线的最佳实践
    本文介绍了微服务上下线的正确姿势,避免使用 kill -9 等粗暴手段,确保服务的稳定性和可靠性。 ... [详细]
  • 兆芯X86 CPU架构的演进与现状(国产CPU系列)
    本文详细介绍了兆芯X86 CPU架构的发展历程,从公司成立背景到关键技术授权,再到具体芯片架构的演进,全面解析了兆芯在国产CPU领域的贡献与挑战。 ... [详细]
  • malloc 是 C 语言中的一个标准库函数,全称为 memory allocation,即动态内存分配。它用于在程序运行时申请一块指定大小的连续内存区域,并返回该区域的起始地址。当无法预先确定内存的具体位置时,可以通过 malloc 动态分配内存。 ... [详细]
  • 浅析python实现布隆过滤器及Redis中的缓存穿透原理_python
    本文带你了解了位图的实现,布隆过滤器的原理及Python中的使用,以及布隆过滤器如何应对Redis中的缓存穿透,相信你对布隆过滤 ... [详细]
  • 本文详细介绍了Java反射机制的基本概念、获取Class对象的方法、反射的主要功能及其在实际开发中的应用。通过具体示例,帮助读者更好地理解和使用Java反射。 ... [详细]
  • 本文介绍如何使用OpenCV和线性支持向量机(SVM)模型来开发一个简单的人脸识别系统,特别关注在只有一个用户数据集时的处理方法。 ... [详细]
  • C语言中全部可用的数学函数有哪些?2.longlabs(longn);求长整型数的绝对值。3.doublefabs(doublex);求实数的绝对值。4.doublefloor(d ... [详细]
  • Spring – Bean Life Cycle
    Spring – Bean Life Cycle ... [详细]
  • 探讨Redis的最佳应用场景
    本文将深入探讨Redis在不同场景下的最佳应用,包括其优势和适用范围。 ... [详细]
  • 利用python爬取豆瓣电影Top250的相关信息,包括电影详情链接,图片链接,影片中文名,影片外国名,评分,评价数,概况,导演,主演,年份,地区,类别这12项内容,然后将爬取的信息写入Exce ... [详细]
  • 本文介绍如何通过 Python 的 `unittest` 和 `functools` 模块封装一个依赖方法,用于管理测试用例之间的依赖关系。该方法能够确保在某个测试用例失败时,依赖于它的其他测试用例将被跳过。 ... [详细]
author-avatar
mobiledu2502877207
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有