3.3 GCC的其他特性
只要C语言代码里使用了字符串型常量(可参照3.1.1节的范例),编译器就会把这个字符串常量置于常量字段,以保证其内容不会发生变化。不过GCC有个有趣的特征:它可能会把字符串拆出来单独使用。
我们来看下面这段程序:
#include <stdio.h>
int f1()
{
printf ("world\n");
};
int f2()
{
printf ("hello world\n");
};
int main()
{
f1();
f2();
};
多数的C/C++编译器(包括MSVC编译器)会分配出两个直接对应的字符串,不过GCC 4.8.1的编译结果则更为可圈可点。
指令清单3.10 在IDA中观察GCC 4.8.1 的汇编指令
> f1 proc near
s = dword ptr -1Ch
sub esp, 1Ch
mov [esp+1Ch+s], offset s ; "world\n"
call _puts
add esp, 1Ch
retn
f1 endp
f2 proc near
s = dword ptr -1Ch
sub esp, 1Ch
mov [esp+1Ch+s], offset aHello ; "hello "
call _puts
add esp, 1Ch
retn
f2 endp
aHello db 'hello'
s db 'world', 0xa, 0
在```
打印字符串“hello world”的时候,这两个词的指针地址实际上是前后相邻的。在调用puts()函数进行输出时,函数本身不知道它所输出的字符串分为两个部分。实际上我们在汇编指令清单中可以看到,这两个字符串没有被“切实”分开。
在f1()函数调用puts()函数时,它输出字符串“world”和外加结束符(数值为零的1个字节),因为puts()函数并不知道字符串可以和前面的字符串连起来形成新的字符串。
时间: 2024-09-20 06:12:45