神奇,C代码竟然能当成shell脚本一样“直接”执行!

 

 

前言

我们都知道,写完了的C代码是需要编译链接之后才能运行的(也许你不需要手动点击编译,但是IDE可能帮你做了这件事),那么能不能让C代码像执行shell脚本或者Python脚本一样,直接可运行呢?类似于:

$ ./main.c

就可以直接运行了。

看起来虽然没啥用,但是感觉有点小刺激。

​小试牛刀

对于文本内容,系统首先会尝试当成shell进行解释执行,这一点还不明白的朋友,建议先阅读《为什么执行命令开头需要./》。

不过话又说回来,.c最终要编译成可执行文件,如果想要它直接执行,那么就得悄悄地在这个过程中做点小动作了。我们试试把编译过程加进去:

#!/usr/bin/gcc  -o main "$0" && ./main
//main.c 公众号编程珠玑
#include<stdio.h>
int main(void)
{
    printf("hello,编程珠玑\n");
    return 0;
}

试一下:

$ ./main.c
./main.c:1:2: error: invalid preprocessing directive #!
 #!/usr/bin/gcc  -o main "$0" && ./main

诶,报错了,看起来像是GCC编译main.c的时候报错了。

仔细一想,这不太正常了吗?很明显第一行就不是C代码的合法内容啊!

再接再厉

怎么办呢?能不能把第一行既能够执行编译,又能够变成合法的C代码内容呢?
这不很简单吗?注释不就是这样的内容吗?

//usr/bin/gcc  -o main "$0" && ./main
//main.c 公众号编程珠玑
#include<stdio.h>
int main(void)
{
    printf("hello,编程珠玑\n");
    return 0;
}

嗯?还真是巧了,对于C代码来说,第一行是注释,对于shell来说,也是一个正常的路径。再试一下:

$ ./main.c
./main.c: line 2: //main.c: No such file or directory
./main.c: line 4: syntax error near unexpected token `('
./main.c: line 4: `int main(void)'

咦?怎么还是报错了?前面说到,这里的内容必须既能被shell识别,又能是合法C代码,显然第二行不符合啊。

投机取巧

很明显,除了第二行,后面的第三行,第四行都不能被当成shell正常执行。那么就果断一点好了,执行完了第一行咱就退出还不行吗?

于是,第一行变成下面这样:

//usr/bin/gcc  -o main "$0" && ./main ;exit

再来执行一下

$ ./main.c
hello,编程珠玑

实际上就达到了下面的效果:

$ gcc -o main main.c && ./main

还能更通用吗?

有人就问了,这里指定了生成文件名,而且如果程序还带了参数怎么办?
但是用//开头已经很取巧了。别忘了,C里面还有终极注释大法:

#if 0
#endif 

而且巧的是,#也是shell脚本的注释符。这就有趣了。

我们改造如下:

#if 0
proName="${0%.*}"  #去掉文件名后缀,作为程序名
gcc -o $proName "$0"
./$proName "$@"   #传入命令行参数
rm $proName
exit
#endif
//main.c 公众号编程珠玑
#include<stdio.h>
int main(void)
{
    printf("hello,编程珠玑\n");
    return 0;
}

现在再来看,是不是符合要求了:

  • 文件名不限定

  • 支持程序传入命令行参数

有人又要问了,如果多文件程序怎么办?

还能怎么办?makefile,cmake bazel等用起来。

总结

好了,秘密也被你知道了,现在一点都不神奇了吧!这里纯属娱乐,仅供学习其中的原理,对于编译链接成可执行程序,构建工具是一个好的选择。

相关精彩推荐

 

 

关注公众号【编程珠玑】,获取更多Linux/C/C++/数据结构与算法/计算机基础/工具等原创技术文章。后台免费获取经典电子书和视频资源

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
第一部分 编 程 技 术 第1章 性能监视工具 3 1.1 计算素数 3 1.2 使用性能监视工具 7 1.3 一个专用的性能监视工具 8 1.4 开发性能监视工具 10 1.5 原理 11 1.6 习题 11 1.7 深入阅读 12 第2章 关联数组 13 2.1 Awk中的关联数组 13 2.2 有穷状态机模拟器 16 2.3 拓扑排序 17 2.4 原理 20 2.5 习题 21 2.6 深入阅读 22 第3章 程序员的忏悔 23 3.1 二分搜索 24 3.2 选择算法 26 3.3 子程序库 28 3.4 原理 30 3.5 习题 31 第4章 自描述数据 33 4.1 名字—值对 33 4.2 记录来历 36 4.3 排序实验 37 4.4 原理 39 4.5 习题 39 第二部分 实 用 技 巧 第5章 劈开戈尔迪之结 43 5.1 小测验 43 5.2 解答 44 5.3 提示 44 5.4 原理 47 5.5 习题 48 5.6 深入阅读 49 5.7 调试(边栏) 49 第6章 计算机科学箴言集 51 6.1 编码 52 6.2 用户界面 53 6.3 调试 53 6.4 性能 54 6.5 文档 56 6.6 软件管理 56 6.7 其他 58 6.8 原理 58 6.9 习题 58 6.10 深入阅读 60 第7章 粗略估算 61 7.1 头脑热身 61 7.2 性能的经验法则 62 7.3 Little定律 64 7.4 原理 65 7.5 习题 66 7.6 深入阅读 67 7.7 日常速算(边栏) 67 第8章 人员备忘录 69 8.1 备忘录 69 8.2 原理 71 8.3 深入阅读 71 第三部分 人性化I/O 第9章 小语言 75 9.1 Pic语言 76 9.2 视角 79 9.3 Pic预处理器 81 9.4 用来实现Pic的小语言 83 9.5 原理 87 9.6 习题 88 9.7 深入阅读 89 第10章 文档设计 91 10.1 表格 92 10.2 三条设计原则 94 10.3 插图 94 10.4 文本 96 10.5 合适的媒介 98 10.6 原理 100 10.7 习题 101 10.8 深入阅读 101 10.9 次要问题目录(边栏) 101 第11章 图形化输出 103 11.1 实例研究 103 11.2 显示结果取样 105 11.3 原理 107 11.4 习题 108 11.5 深入阅读 110 11.6 拿破仑远征莫斯科(边栏) 110 第12章 对调查的研究 113 12.1 有关民意调查的问题 113 12.2 语言 114 12.3 图片 117 12.4 原理 119 12.5 习题 120 第四部分 算 法 第13章 绝妙的取样 123 13.1 取样算法一瞥 123 13.2 Floyd算法 124 13.3 随机排列 125 13.4 原理 127 13.5 习题 127 13.6 深入阅读 128 第14章 编写数值计算程序 129 14.1 问题 129 14.2 牛顿迭代 130 14.3 良好的起点 132 14.4 代码 133 14.5 原理 135 14.6 习题 135 14.7 深入阅读 137 14.8 数值算法的力量(边栏) 137 第15章 选择 141 15.1 问题 141 15.2 程序 142 15.3 运行时间分析 145 15.4 原理 148 15.5 习题 149 15.6 深入阅读 151 附录A C和Awk语言 153 附录B 一个子程序库 157 部分习题答案 165 索引 181

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值