前天收到了K&R的中文版的书,期盼已久的书啊,心情有点小激动。
【练习1-1】
在“Hello world”程序中制造混乱。
这个我倒不是很想做,因为我自己不是个制造混乱的人,虽然有时在写代码的时候不能由自己控制,我倒是希望能在代码中寻找 ladybug,嘻嘻。
这里我们来看点别的:
1、ELF
我们在Linux下面编译好后Hello world程序后,运行的过程很简单;但是我一直想探探,这里到底发生了什么。如果你对机器码比较精通,那么
od可以帮你解决这个问题,可问题是我不明白,因此我需要“曲线救国”。
我是这么编译的: gcc -Wall hello.c -o hello
很幸运,没有错误,我能够运行我的程序,但是我不想看自己运行的结果,我这么做了:
less hello, 结果Linux告诉我这个文件可能是二进制文件,问我是否依然打开,这里当然要打开了,我不打开找你Linux哥哥干嘛。
输出结果大家可以自己看看,我们先来看一行输出:
看到什么了,一堆的^A^A和^@, 我现在对这些不感兴趣,感兴趣的是前面的四个字符:
我们看到了:ELF,这个是啥意思呢?我们这里看一段引自维基百科的内容容:
就是说,ELF表示这个文件一个可以连接和可执行的格式,也就是说这是一个binary格式的文件,等会我们还可以单独编译一个函数试试。
至于ELF格式,在连接上有简要的说明。
2、链接的库
我们知道,在汇编器将.asm文件翻译成.o文件后,还需ld将.o文件链接成最终的可执行文件,这里就需要用到预编译的库文件,那么我们如何
查看文件链接了那些库文件呢?别着急,虽然唐僧被老鼠精抓了,好歹他俩成不了亲,听我慢慢道来,我们可以看到下面这样一段输出:
咿呀,看到了没,亲们,这里指出了我们链接时用到的库文件了,/lib/ld-linux.so.2, 大家可以搜索一下,在你的计算机里面(如果你安装的时候
选择了安装开发工具的话)应该能找到这个文件。
这个文件是一个动态连接器文件,在链接的时候需要用到,从 ld 这个前缀可以看出,他与链接器ld相关。其实这里面还提示了很多其他的库文件。
3、GNU
整个输出里面还有三个字母比较醒目,那就是:GNU, 没想到吧,在你编译生成的目标文件里面居然还有GNU三个字母。
4、Hello world 字符串
在整个文件,还有一个比较醒目的地方:Hello world,这里也能看到
这个地方就是我们将要输出的字符
5、系统信息,编译器信息,文件节区信息
这里我们可以清楚的看到: .text、 .data 、 .bss、 .comment这些节区关键字的信息,
我们可以看看我的GCC的版本信息,是否和这里提示的一样。
很明显,这里提示的信息与我们利用less查看的hello文件一致。
6、readelf程序
其实Linux不但提供了二进制形式的二进制文件查看工具od,还提供了一个更可视化的查看工具,readelf。我们可以看看readelf与less查看的内容有啥不一样的
这里可以看到,里面的输出内容与less命令输出的有很多相似的地方,如果你对readelf比较熟悉的话,那么结合less 命令,是不是能更好的理解呢?
7、 objdump
如果需要查看更加具体的内容,那么我们还可以利用objdump工具,例如需要查看所有segment的内容,可以这样: objdump -x hello
输出结果如下:
可以看出,objdump提供的信息比readelf工具更详细。如果你对elf文件的分析感兴趣可以到这个链接看看:http://wenku.baidu.com/view/5ca21b28915f804d2b16c164.html
【练习1-2】
在printf函数使用 ‘\c’, 看看输出结果是什么,你说呢? 会输出啥玩意
我们看到,printf输出的时候,并没有按照我们通常理解的那样,字符串字面值原样输出,这个很多人都是这么认为的,实际? 这个在最初【C语言学习趣事】的时候,我曾经说过这个问题
我敢猜测,我们很多人在学习的时候,你的老师说过这样话: printf函数的第一个参数的内容,如果不是用格式控制和转义序列则原样输出。想想,你的老师是否这么说过。
这是什么原因呢? 噜啦啦
【练习1-3】
【练习1-4】
【练习1-5】
这三个练习,需要注意的是整数的除法。