【C语言】一句printf代码——{ a[0] ? 0[a] }
这是前段时间做的http://fun.coolshell.cn/中的一道题,很有意思,涉及的其实是C的基础,不过当时第一次看见这行代码确实把我弄懵了:
printf(&unix["\021%six\012\0"], (unix)["have"] + "fun" - 0x60);
当时在网上一搜,有仁兄给出了全句的解释:http://blog.itpub.net/12443821/viewspace-671745/
这里呢,我就用我的理解再解释一下,至少更符合我的理解思路~我是第一次见这种写法,C语言前辈们请略过~
分成下面几个部分来解析这行代码:
一、\021 \012 \0是什么意思
\abc表示是八进制表示的ASCII码,所以\021就是17对应的ASCII码(2^8+1=17),\012是10,\0就是0,所以,代码约等于下面的表示,ascii的17表示的字符有点怪,就用@代替:
printf(&unix["@%six\n"], (unix)["have"] + "fun" - 0x60);
二、unix是什么
这个确实不大容易知道,如果在windows上运行这行代码,是要报错的,因为没有定义unix,这是传说中编译器内置的宏,可能是gcc内置的吧,没有查过,反正相当于有:
#define unix 1
三、(0[a] == a[0]) ? true : false
下面就看看(unix)["have"]是什么东西,当时我就是被这个弄懵了,就算知道unix表示1,那么1["have"]是啥啊?
char *b = "qwe";
printf("%c", b[]);
看看这两行的输出是啥,很明显,输出字符数组b的第二项"w",这个大家都知道,而且大家也都很清楚,这实际上是:
printf("%c", *(b+));
这个原理就很明显了,b[1]等价于*(b+1)等价于*(1+b),而1[b]不就正表示这个地址嘛~
到了这就一切清晰了,上面的代码就变成了:
char * s1 = "have";
char * s2 = "fun";
printf(&unix["@%six\n"], s1[] + s2 - 0x60);
四、地址运算
s1[1]+s2-0x60,这个对应前面的%s,是个字符串,很明显,s1[1]是一个char(这里表示字母a),或者是一个数(a的ascii码97,或十六进制表示0x61)。
s2是"fun"这个字符串的首字符地址,0x60是个数,所以s1[1]-0x60先进行运算,得到1,于是该问题变为:
char * s2 = "fun";
printf(&unix["@%six\n"], s2 + );
s2+1就是un了,也就是前面的%s,于是世界一下子清晰了:
printf(&unix["@unix\n"]);
五、柳暗花明
先看unix["@unix\n"],和前面一样,表示(前面直接删掉\0并不很合理,用变量s来声明,这个\0就是自动被添加的了):
char * s = "@unix\n";
printf(&s[]);
s[1]表示字母u,&s[1]表示u的地址,就变成了输出"unix\n"。
所以最终的结果就是unix。
【C语言】一句printf代码——{ a[0] ? 0[a] }的更多相关文章
- 黑马程序员-- C语言变量作用域与代码块
这里通过变量作用域的两种错误用法来介绍一下C语言变量作用域 其次对代码块的使用进行了简单说明: #include <stdio.h> 1.变量的作用域(作用范围) 变量定义的那一行开始,直 ...
- 『Python CoolBook』C扩展库_其六_从C语言中调用Python代码
点击进入项目 一.C语言运行pyfun的PyObject对象 思路是在C语言中提供实参,传给python函数: 获取py函数对象(PyObject),函数参数(C类型) 获取GIL(PyGILStat ...
- 为什么说JAVA中要慎重使用继承 C# 语言历史版本特性(C# 1.0到C# 8.0汇总) SQL Server事务 事务日志 SQL Server 锁详解 软件架构之 23种设计模式 Oracle与Sqlserver:Order by NULL值介绍 asp.net MVC漏油配置总结
为什么说JAVA中要慎重使用继承 这篇文章的主题并非鼓励不使用继承,而是仅从使用继承带来的问题出发,讨论继承机制不太好的地方,从而在使用时慎重选择,避开可能遇到的坑. JAVA中使用到继承就会有两 ...
- C# 语言历史版本特性(C# 1.0到C# 7.1汇总更新) C#各版本新特性 C#版本和.NET版本以及VS版本的对应关系
C# 语言历史版本特性(C# 1.0到C# 7.1汇总更新) 2017年08月06日 11:53:13 阅读数:6705 历史版本 C#作为微软2000年以后.NET平台开发的当家语言,发展至今具有1 ...
- c语言心形告白代码实现
c语言心形告白代码实现 1.彩色告白 include<stdio.h> include<math.h> include<windows.h> include< ...
- 一句jQuery代码返回顶部
一句jQuery代码返回顶部 效果体验: http://hovertree.com/texiao/yestop/ 使用方法: 只需引用jQuery库和YesTop插件,然后一句代码就可以实现返回顶部: ...
- Swift - 2.3的代码到3.0的转变
分享一下学习新语法的技巧:用Xcode8打开自己的Swift2.3的项目,选择Edit->Convert->To Current Swift Syntax- 让Xcode帮我们把Swift ...
- [转载]Eziriz .NET Reactor 4.7.0.0 官方原版+破解补丁(强大的代码保护和软件防盗版工具)
Eziriz .NET Reactor 是一个强大的代码保护和软件防盗版工具,完全由.NET框架编写..NET Reactor支持NET平台的软件许可系统,并支持NET程序集所有语言.当.Net编译器 ...
- C语言实现md5函数代码
网上找到的实现md5函数代码,包括一个头文件md5.h和一个源文件md5.c,用下面的测试代码test.c测试通过,各文件依次如下: 头文件md5.h #ifndef MD5_H #define MD ...
随机推荐
- Mac air苹果笔记本安装Win10双系统教程(绝对能成功,超详细!)[转]
转自:http://www.xitonghe.com/jiaocheng/anzhuang-4676.html 在MAc苹果电脑,Mac air上安装Windows7相信大家都已经会了吧,好吧Win7 ...
- Android大神 博客
https://github.com/yeungeek/awesome-android-person Android大神 受Trinea的开源项目的启发和参考,也准备列一列Android圈里的大神们. ...
- (转)Kettle命令行
kettle使用命令行来运行ktr和kjb 1:cmd方式运行 1.ktr的运行:运行transformation文件是通过Pan.bat来运行的. 打开cmd命令行窗口,转到Pan.bat所在的目录 ...
- luogu P1941 飞扬的小鸟
题目描述 Flappy Bird 是一款风靡一时的休闲手机游戏.玩家需要不断控制点击手机屏幕的频率来调节小鸟的飞行高度,让小鸟顺利通过画面右方的管道缝隙.如果小鸟一不小心撞到了水管或者掉在地上的话,便 ...
- html特殊字符编码问题导致的细节问题
今天在写前端html时,一个a标签的链接地址,由于链接地址需要给后台传参数,因此带了部分url参数: 在html源码里写的连接地址是: http://域名/bidder/noticesearch?no ...
- new子类会先运行父类的构造函数
发现子类构造函数运行时,先运行了父类的构造函数.为什么呢? 原因:子类的所有构造函数中的第一行,其实都有一条隐身的语句super(); super(): 表示父类的构造函数,并会调用于参数相对应的父类 ...
- 推荐一个好的数据库工具Embarcadero DBArtisan
最近的项目中用到了DB2数据库,由于DB2数据库客户端在操作操作和控制方面不是很方便,如存储过程的编写.后来我们在数据库的操作都转在DBArtisan上了,最新版好像是8.12. 下面介 ...
- 【京东个人中心】——Nodejs/Ajax/HTML5/Mysql爬坑之静态页面
一.引言 接着上一篇,京东个人中心的所有功能数据分析完成之后,现在需要把静态页面完成,实现过程中要用到的技术有:Bootstrap.html5表单新特性等.除此之外,还要利用Node.js的Expre ...
- Spring boot Security Disable security
When I use security.basic.enabled=false to disable security on a Spring Boot project that has the fo ...
- 【Python】使用scatter()绘制散点图
绘制简单散点图 要绘制单个点,使用scatter()函数,并向它传递一对x和y坐标,它将在指定位置绘制一个点 import matplotlib.pyplot as plt plt.scatter(2 ...