c语言字符串替换SI IS,关于c ++:s [j] = si]; 尝试复制字符时出现分段错误

我从某个地方获取了该程序,并试图理解它。

这行:s[j++] = s[i];是崩溃的原因。 我的理解是,至少第一次程序不会崩溃,因为j以后会增加。 第一次j和i的值将为0。

因此,这将类似于s [0] = s [0];

为什么会崩溃?

#include

using namespace std;

void squeeze(char a[], char c);

int main()

{

squeeze("qwiert", 'i');

return 0;

}

void squeeze(char s[], char c)

{

int i, j;

for (i = j = 0; s[i] != '\0'; i++)

{

if (s[i] != c)

{

std::cout <

i:" << s[i];

s[j++] = s[i];

std::cout <

j:" << s[j];

std::cout <

j :" << j;

exit(0);

}

}

s[j] = '\0';

}

输出:

i: q

之后,程序崩溃。

我已经将exit语句停止了指向该段的程序。

为s保留的地址空间可以写保护吗?因为在main()中,它的定义类似于常量,因此编译器可以将其放入特殊的内存区域。但这只是一个猜测。

是的,那是原因。 @KillPinguin

编译时收到以下警告:" ISO C ++禁止将字符串常量转换为char * [-Wwrite-strings]"。一些编译器会完全拒绝此操作(从技术上来说,所有人都应该如此),并给您一个错误。该程序将带有警告编译,但是警告表示某些东西不是完全符合犹太洁食原则,并且该程序很可能不会按照您期望的方式运行。

@ user4581301,实际上标准中没有任何内容强制要求完全拒绝UB。虽然这可能是一个好功能,但您可能应该区分需要什么和有用。

在C ++ 11中@paxdiablo将字符串文字直接转换为char*的操作被正式禁止,但是,是的,我不知道Aquarius_Girl编译的标准是什么。

@ user4581301,C ++ 03中存在相同的措词,尽管在2.13.4中存在了很长时间。病态更新我的答案,以包括在内。

@ paxdiablo我也找不到。 Ive遇到编译器错误,并有一般评论将其称为事实,但我无法在最近的标准中找到彻底的禁令。并不意味着2003年有一个例外,它允许进行2011年没有的转换,但我无法使用C ++ 2014之前的任何版本。

Ive还一直在研究隐式转换和初始化规则。

在附录C(di?.lex):char* p ="abc"; valid in C, invalid in C++中找到了它,但在阅读它引用进行此调用的规则时,无法建立相同的连接。

您正在将字符串常量"qwiert"传递给squeeze函数。然后,此函数尝试修改该字符串常量,这是非法的。这会导致核心转储。

为此,您需要传递一个数组:

int main()

{

char str[] ="qwiert";

squeeze(str, 'i');

return 0;

}

刚刚尝试过。 问题已解决。 非常感谢您。

您不得使用以下方式更改字符串文字:

squeeze("qwiert", 'i');

标准(a)的几乎所有迭代都涵盖了这一点:

C++03 2.13.4.String literals [lex.string] /2;

C++11 2.14.5.String literals [lex.string] /12;和

C++14 2.14.5.String literals [lex.string] /13。

每个中存在相同的措词:

Whether all string literals are distinct (that is, are stored in nonoverlapping objects) is implementation-defined. The effect of attempting to modify a string literal is undefined.

在最新的C ++ 17标准中,措词已稍有变化,但大致相同,目前为C++17 5.13.5.String literals [lex.string] /16:

Whether all string literals are distinct (that is, are stored in nonoverlapping objects) and whether successive evaluations of a string-literal yield the same or a different object is unspecified. [Note: The effect of attempting to modify a string literal is undefined. - end note]

我建议您尝试类似的方法:

char str[] ="qwiert"; // Make a writable copy.

squeeze(str, 'i');     //   then fiddle with that.

(a)该答案中的ISO引号实际上是在暗示为什么会这样。

我们并不总是拥有数千兆字节的机器,通常情况下,在早期的编译器中必须采取某些步骤来进行优化(大多数情况下使用C语言,但由于其最初的实现是C语言的前端,因此已延续到C ++中)。

为此,具有相同字符(或以某些方式重叠的字符,例如"successful"和"unsuccessful")的两个字符串可以共享相同的内存以减少空间。

当然,这意味着您不能在不影响另一个的情况下更改一个,这就是为什么要应用此规则的原因。

其他答案指出了问题以及如何解决。

我想指出,您可以通过提高编译器的警告级别来检测此类错误。

使用g++ -Wall,我收到以下警告消息:

socc.cc: In function ‘int main()’:

socc.cc:10:26: warning: ISO C++ forbids converting a string constant to ‘char*’ [-Wwrite-strings]

squeeze("qwiert", 'i');

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值