首先这个是我在2012-06-15日去某公司面试遇到的问题,当时写错了,被鄙视了,现在痛定思痛,深入分析一下。
1 char a[]="abc"; 2 char b[]="abc"; 3 4 char *c="abc"; 5 char *d="abc"; 6 7 const char e[]="abc"; 8 const char f[]="abc"; 9 10 const char *g="abc"; 11 const char *h="abc"; 12 printf("%i\n",a==b); 13 printf("%i\n",c==d); 14 printf("%i\n",e==f); 15 printf("%i\n",g==h);
正确答案是:0 1 0 1
额,悲催的是我刚好答反了,不知道当时怎么想的了。
现在我把这段程序用objdump反汇编后来分析分析:
1 8048594: 55 push %ebp 2 8048595: 89 e5 mov %esp,%ebp 3 8048597: 83 ec 20 sub $0x20,%esp 4 804859a: a1 00 87 04 08 mov 0x8048700,%eax 5 804859f: 89 45 fc mov %eax,-0x4(%ebp) 6 80485a2: a1 00 87 04 08 mov 0x8048700,%eax 7 80485a7: 89 45 f8 mov %eax,-0x8(%ebp) 8 80485aa: c7 45 f4 00 87 04 08 movl $0x8048700,-0xc(%ebp) 9 80485b1: c7 45 f0 00 87 04 08 movl $0x8048700,-0x10(%ebp) 10 80485b8: a1 00 87 04 08 mov 0x8048700,%eax 11 80485bd: 89 45 ec mov %eax,-0x14(%ebp) 12 80485c0: a1 00 87 04 08 mov 0x8048700,%eax 13 80485c5: 89 45 e8 mov %eax,-0x18(%ebp) 14 80485c8: c7 45 e4 00 87 04 08 movl $0x8048700,-0x1c(%ebp) 15 80485cf: c7 45 e0 00 87 04 08 movl $0x8048700,-0x20(%ebp) 16 80485d6: b8 00 00 00 00 mov $0x0,%eax 17 80485db: c9 leave 18 80485dc: c3 ret
我们来把c语言代码和汇编代码对比着分析:
前三句是进入main函数时保护现场,压栈操作,不用管。
char a[]="abc"; 对应: mov 0x8048700,%eax mov %eax,-0x4(%ebp)
对比着这两句汇编代码来分析这句c语言代码:
- 因为“abc”是常量,首先在常量区申请一块内存存放“abc”,地址为:0x8048700;
- 然后把0x8048700地址指向的数据拷贝到寄存器%eax中;
- 最后把%eax的值拷贝到-0x4(%ebp)中,也就是字符数组a中。
我们知道%ebp是一个栈寄存器,所以从这里看出字符数组的数据是存放在栈上的。
char b[] ="abc";对应6,7行汇编代码,和上面一样。
char *c="abc"; 对应: movl $0x8048700,-0xc(%ebp)
我们看到汇编代码中是把$0x8048700这个立即数直接拷贝到-0xc(%ebp)中的。
$0x8048700是什么呢?是字符串“abc”的地址,编译器很聪明,同样的字符串在内存里只存放了一份。
地址前面加上$是说明这个操作是个立即数寻址方式,也就是把这个数字拷贝到-0xc(%ebp)。
从这我们可以看出字符指针本身是在栈上,它指向的值在常量区的。
继续看汇编代码,我们发现const 型和非const型的汇编代码是一样的。这是因为const的实现机制是编译器在编译时会对const型变量进行检查,如果发现违反const型用法则报错。就是说const型变量在编译期间是不允许改变的,那么在运行时呢?可以的,只要骗过了编译器就可以改变,具体可以看《高质量程序设计指南--c++/c语言》86页的程序。
现在我们来回答下这个问题:
printf("%i\n",a==b);
数组的名称是指向这个数组的第一个单元的指针,因此a,b的值是数组a,b的首地址。
这两个数组的地址当然是不一样的,因此是0.
printf("%i\n",c==d);
字符指针c和d的值是指向"abc"这个常量的地址,因此是一样的。答案是1.
const型字符数组和const字符指针同理。
reference:
《高质量程序设计指南--c++/c语言》 第五章 c++/c常量
《深入理解计算机系统》 第三章 程序的机器级表示
作者:辛未
转载请署名!
2012-06-17