C语言问题一则

本文通过实验探讨了在C语言中直接修改字符串字面量的行为。使用四种不同的编译器进行了测试,揭示了它们对此行为的不同处理方式。并进一步通过GCC生成的汇编代码解析了这一现象背后的原因。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

C语言问题一则

摘自: huangyaoshifog的专栏 http://blog.youkuaiyun.com/huangyaoshifog

首先,来看如下一段程序
char* xyzstring = "hello,world!";
int main(void)
{
 xyzstring[0] = 'a';
 printf("%s/n",xyzstring);
 return 0;
}

这段程序有问题吗?有,xyzstring的数据应该是静态数据,不能被修改。对,C语言的标准上也是这样说的。

果然是这样吗,我们做一个测试,使用四种编译器来看看实际运行的情况。

Codewarrior 8.0、Visual C++ 6.0、Borland C++ 5.6编译后运行都没有问题,都打出了"aello,world!",GCC 3.2编译后运行程序死掉。

为什么会出现这种情况,答案很简单,GCC将"hello,world!"放到了.text段中,而其它三种编译器则是将"hello,world!"到了.data段中。程序中,.text段是用来存放代码的,因此不能被修改,所以,当我们用xyzstring[0]来修改其中内容的时候,程序当然会当掉了。而.data段因为是数据段,是可以被修改的,因此程序不会当掉。

下面为了验证以上说法,我们使用GCC将源代码汇编成test.s

运行如下命令gcc -S test.c
 .file "test.c"
.globl _xyzstring

 .text
LC0:
 .ascii "hello,world!/0"
 .data
 .align 4
_xyzstring:
 .long LC0
 .def ___main; .scl 2; .type 32; .endef
 .text
LC1:
 .ascii "%s/12/0"
 .align 2
.globl _main
 .def _main; .scl 2; .type 32; .endef
_main:
 pushl %ebp
 movl %esp, %ebp
 subl $8, %esp
 andl $-16, %esp
 movl $0, %eax
 movl %eax, -4(%ebp)
 movl -4(%ebp), %eax
 call __alloca
 call ___main
 movl _xyzstring, %eax
 movb $97, (%eax)
 subl $8, %esp
 pushl _xyzstring
 pushl $LC1
 call _printf
 addl $16, %esp
 movl $0, %eax
 leave
 ret
 .def _printf; .scl 2; .type 32; .endef

以上是输出结果,我们看到test.s的头两行是
.globl _xyzstring
.text

说明_xyzstring是定义在了.text段中,现在,我们将其改称如下
.globl _xyzstring
.data

然后编译gcc -o test.exe test.s,接着执行test.exe,出现了什么,哈哈"aello,world!",执行没有问题了。

以上就是不同编译器对这种类型代码的解决方法,但是为了兼容,我们绝对不应该写出上面的代码。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值