用C语言模仿Python函数
首先得说明一点,C 语言不是函数式编程语言,要想进行完全的函数式编程,还得先写个虚拟机,然后再写个解释器才行(相当于 CPython )。
下面我们提供一个例子,说明即便不写虚拟机, C 语言函数也是可以“适度地模仿” Python 函数。
我们有如下的 Python 程序:
def line_conf(a, b):
def line(x):
return a*x + b
return line line1 = line_conf(1, 1)
line2 = line_conf(4, 5)
print(line1(5), line2(5))
Python Code
我们在C程序中适度地模拟其中的line_conf函数:
/* MIT License Copyright (c) 2017 Yuandong-Chen Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE. */ /////////////////////////////////////////////////////////////////////////////// // Note: The C program is almost equivalent to the Python program as follows:
// def line_conf(a, b):
// def line(x):
// return a*x + b
// return line
//
// line1 = line_conf(1, 1)
// line2 = line_conf(4, 5)
// print(line1(5), line2(5)) #include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <stdarg.h> typedef int Func(); Func *line_conf(int x, int y,...)
{
va_list ap;
va_start(ap, y); asm volatile(
"push %%eax\n\t"
"subl $40, %%esp\n\t"
"movl 8(%%ebp), %%eax\n\t"
"movl %%eax, -36(%%ebp)\n\t"
"movl 12(%%ebp), %%eax\n\t"
"movl %%eax, -40(%%ebp)\n\t"
"addl $40, %%esp\n\t"
"pop %%eax\n\t"
:::"memory"
); if(va_arg(ap,int) == ){ LINE: asm volatile(
"push %%ebp\n\t"
"movl %%esp, %%ebp\n\t"
"movl 8(%%ebp), %%eax\n\t"
"imul -36(%%ebp), %%eax\n\t"
"addl -40(%%ebp), %%eax\n\t"
"movl %%ebp, %%esp\n\t"
"pop %%ebp\n\t"
"ret\n\t"
:::"memory","%eax"
);
}
__END:
va_end(ap);
return (Func *)(&&LINE);
} int main(int argc, const char *argv[]){
printf("====TEST START====\n");
printf("34*234+6 ?= %d\n",line_conf(,)());
printf("1*3+2 ?= %d; 324*65+3 ?= %d; 13*66+2 ?= %d\n",line_conf(,)(),line_conf(,)(),line_conf(,)()); int fd = line_conf(,)();
Func *fun = line_conf(,);
int a = ; // Limited point
printf("3*3+3 ?= %d; 1*4+6 ?= %d\n",fun(),fd);
printf("====TEST END====\n");
return ;
} // Compile it by the following command:
// gcc -m32 -O0 -fno-stack-protector CFunctional.c; ./a.out
// The terminal output should looks like:
// ====TEST START====
// 34*234+6 ?= 7962
// 1*3+2 ?= 5; 324*65+3 ?= 21063; 13*66+2 ?= 860
// 3*3+3 ?= 12; 1*4+6 ?= 10
// ====TEST END====
//Note: The limitation happens between line 86 and line 88, we cannot insert any function here
// whose stack is larger than 40 bytes.(Why is 40? check the inline assembler language)
C Code
结果在MacOSX和Ubuntu上(i386)都能通过简单的测试。但是可以看到,仅仅是简单的模拟,我们也得用到大量(按比例)的汇编,可读性很差,而且模拟程度非常有限,代码长度也更长。
注意:这只是个玩具,别这么写代码,除非想搞破坏(充斥着各种漏洞,极易被侵入)。
用C语言模仿Python函数的更多相关文章
- 在使用python语言的open函数时,提示错误OSError: [Errno 22] Invalid argument: ‘文件路径’
如题,在使用python语言的open函数时,提示错误OSError: [Errno 22] Invalid argument: '文件路径',在查阅了大量资料后也得到了一些解决方案,但是这些解决方案 ...
- Python函数参数默认值的陷阱和原理深究"
本文将介绍使用mutable对象作为Python函数参数默认值潜在的危害,以及其实现原理和设计目的 本博客已经迁移至: http://cenalulu.github.io/ 本篇博文已经迁移,阅读全文 ...
- C语言扩展Python模块
1. 先创建一个PythonDemo.cpp文件: //c/c++中调用python脚本,配置步骤参见上一篇:C/C++与python交互 \ C/C++中调用python文件. #include ...
- Python开发【第三章】:Python函数介绍
一. 函数介绍 1.函数是什么? 在学习函数之前,一直遵循面向过程编程,即根据业务逻辑从上到下实现功能,其往往用一长段代码来实现指定功能,开发过程中最常见的操作就是粘贴复制,也就是将之前实现的代码块复 ...
- Python函数解析
对于Python的函数,我们需要记住的是: 1. 函数的默认返回值是None. 2. python是一个自上而下逐行解释并执行的语言.因此,函数的定义必须在函数被调用之前.同名的函数,后定义的会覆盖前 ...
- Python入门笔记(18):Python函数(1):基础部分
一.什么是函数.方法.过程 推荐阅读:http://www.cnblogs.com/snandy/archive/2011/08/29/2153871.html 一般程序设计语言包含两种基本的抽象:过 ...
- python函数的返回值 讲解
我们一起来聊聊python函数返回值的特殊情况,之前我也碰到过类似方面的问题,到后来查阅了一些资料后,发现原来是这样. 首先,写函数的时候,一定要写函数的文档,这样方便我们识别函数是做什么的.我记得很 ...
- windows 下 使用codeblocks 实现C语言对python的扩展
本人比较懒就粘一下别人的配置方案了 从这开始到代码 摘自http://blog.csdn.net/yueguanghaidao/article/details/11538433 一直对Python扩展 ...
- python函数的参数传递问题---传值还是传引用?
摘要:在python中,strings, tuples, 和numbers是不可更改的对象,而list,dict等则是可以修改的对象.不可更改对象的传递属于传值,可更改对象属于传引用.想要在函数中传递 ...
随机推荐
- 获取VB类模块成员函数指针(转)
最近在做一些VB6.VBA的项目,被如何获取类模块中的函数指针这个问题所困扰,收集整理后,有2分资料值得收藏,特将关键部分留存,以备后续查找. 参照连接1:http://www.cnblogs.com ...
- 测试一下js是否可用
昨天刚获批通过了js权限,今天写一段小代码测试下是否可用 我用Javascript添加了 <p> <script type="text/javascript" ...
- “this kernel requires an x86-64 CPU, but only detects an i686 CPU, unable to boot” 问题解决
1. 问题描述: 在Virtual Box上安装 Ubuntu 系统时出现错误(如题),VIrtual Box 上也没有64位操作系统的选项 2.原因分析: (1) 可能 BIOS 的 Virtua ...
- 使用HTML5的canvas做图片剪裁
前言 图片裁剪上传,不仅是一个很贴合用户体验的功能,还能够统一特定图片尺寸,优化网站排版,一箭双雕. 需求就是那么简单,在浏览器里裁剪图片并上传到服务器. 我第一个想到的方法就是,将图片和裁剪参数(x ...
- 08 Noise and Error
噪声:误标.对同一数据点的标注不一致.数据点信息不准确... 噪声是针对整个输入空间的. 存在噪声的情况下,VC bound依旧有用: 存在噪声,就是f--->p(y|x),f是p的特殊情况:如 ...
- SQL编程的一些良好好习惯
|转载自:cnblog |原文链接:http://www.cnblogs.com/MR_ke/archive/2011/05/29/2062085.html 我们做软件开发的,大部分人都离不开跟数据库 ...
- Java中常用来处理时间的三个类:Date、Calendar、SimpleDateFormate,以及Java中的单例设计模式:懒汉式、饿汉式以及静态内部类式
(一)java.util.Date类 1.该类有一个long类型的属性:用来存放时间,是用毫秒数的形式表示,开始的日期是从1970年1月1号 00:00:00. 2.该类的很多方法都已经过时,不 ...
- 【Azure】Azure学习方法和学习资料
学习方法: DEX为入门培训,fundamental book进阶材料,Azure 官方为补充权威材料,网站一些大拿的Blog是很多实践精华,推荐阅读. 推荐教材和学习内容: EDX培训:http:/ ...
- 如何通过Mysql的二进制日志恢复数据库数据
经常有网站管理员因为各种原因和操作,导致网站数据误删,而且又没有做网站备份,结果不知所措,甚至给网站运营和盈利带来负面影响.所以本文我们将和大家一起分享学习下如何通过Mysql的二机制日志(binlo ...
- 简单的总结一下iOS面试中会遇到的问题
1.线程是什么?进程是什么?二者有什么区别和联系? 一个程序至少有一个进程,一个进程至少有一个线程: 进程:一个程序的一次运行,在执行过程中拥有独立的内存单元,而多个线程共享一块内存 线程:线程是指 ...