测试平台:
Ubuntu 16.04 Windows Mingw GCC gcc version 5.3.0 (i686-posix-dwarf-rev0, Built by MinGW-W64 project)编译器:GCC 5.3
开始不得不吐槽一下网上那些所谓“C语言字符串翻转”的实现的哥们啊,我看到他们代码#include<iostream>
和引入STL的时候我都不知道我是该哭还是该笑。 好吧我们开始,从一个简单的问题去分析问题。 先贴代码: 这是我实现的: #includevoid s_reverse(char *s) { char *h = s; char *t = s; char ch; /* t指向s的尾部 */ while (*t++) {}; t--; /* 与t++抵消 */ t--; /* 回跳过结束符'\0' */ /* 当h和t未重合时,交换它们所指向的字符 */ while (h < t) { ch = *h; *h++ = *t; /* h向尾部移动 */ *t-- = ch; /* t向头部移动 */ }}int main() { char str[] = {'H','e','l','l','o','\0'};//为啥分成两个后面说 char *str_1 = "Hello, World!"; printf("origin str ---> %s\n",str); printf("origin str_1 ---> %s\n",str_1); s_reverse(str); s_reverse(str_1);#ifdef _MSC_VER printf("%s\n", str, "Visual Stadio 2017"); printf("str--->%s\n",str); printf("str_1--->%s\n",str_1);#else printf("str--->%s\n",str); printf("str_1--->%s\n",str_1);#endif return 0;}
这是自带的:
#includeint main() { char *str ="Hello, World!"; strrev(str); return 0;}
只关注str_1现在分别来看看它们在Mingw下的表现(注:这里Mingw下的效果和Linux测试一致)和MSVC下的表现
MyCode on Mingw![](https://oscimg.oschina.net/oscnet/dc26feb78ddd9d9eb68c89cddd634699a17.jpg)
![](https://oscimg.oschina.net/oscnet/56067f8f889c02d22beaca5c86f4a6918d2.jpg)
![](https://oscimg.oschina.net/oscnet/c25bb6503f541c1fef22461b8ff3b197f0c.jpg)
![](https://oscimg.oschina.net/oscnet/b4020a29d3f9a73eff7cab1698b15d98f56.jpg)
gcc ./main.c -Sgcc ./str.c -S
现在分别生成了两份代码 main.s里面我们可以看到这么一段
LC0: .ascii "Hello, World!\0"
是的这玩意被定义为常量了,无法被访问
使用数组形式声明字符串char str[] = {'H','e','l','l','o','\0'};
然后我们注释掉str_1相关的东西再来看看str。
![](https://oscimg.oschina.net/oscnet/58be22f7dcf23c494675c5e800094f1d7b8.jpg)
call _strrev
,所以我们根据他的原型,用上面自己实现的代码去寻找问题根源。 gdb main.exe
break s_reverse
按下r运行
![](https://oscimg.oschina.net/oscnet/6e327330f43b1d7576bd71dda744c757574.jpg)
disassemble
命令来查看汇编代码 汇编步进调试ni
![](https://oscimg.oschina.net/oscnet/b192db6e443e5613733357b3c361945999a.jpg)
mov %dl,(%eax)
这句话的意思是从数据寄存器DX低位取数据放到eax中,但是此时数据寄存器是不可写的,所以抛出了异常中断
参考文献:
[DWARF4][.cfi指令解读]
[剑指offer]
[汇编中的寄存器]