当我声明并运行以下内容时,它会给我一个segmentation fault。
main()
{
char *p = "boa";
*(p+1) = 'y';
printf("%s",p);
}
我怀疑char *p
是一个常数等等。
但以下工作正常。
main()
{
int i = 300;
char *p = (char*)&i;
*(p+1) = 'y';
printf("%s",p);
}
这背后的原因是什么?上述规则也不适用于此吗?
答案 0 :(得分:3)
这取决于你对“工作正常”的定义。但是赋值不是分段错误的原因是因为p
指向i
变量的地址,这显然不是常数。 i
被赋予了一个常量值,但i
本身不是常量。
对于i = 300
(假设小端x86):
+--+--+--+--+
i:|2c|01|00|00|
+--+--+--+--+
.
/|\
|
p:&i
*(p+1) = 'y'
之后
+--+--+--+--+
i:|2c|79|00|00|
+--+--+--+--+
.
/|\
|
p:&i
因此,print语句恰好为您打印,y
,但这只是因为您依赖于平台的字节顺序(2c
是一个可打印的ASCII字符)。在大端机器上,和/或它是非ASCII的情况可能会有所不同。
答案 1 :(得分:1)
哦,男孩......
第一个由于字符串为const
而导致的seg-faults(你已经做到了这一点)。然而,第二个是对指针语义的迷人滥用! ; - )
以下是您在第二个示例中所做的事情:
int
号码(在您的情况下为300
)int
的地址 - 基本上是一个地址,该地址包含(32位?)int
300并将其转换为char*
,其中每个元素指向8位值答案 2 :(得分:1)
区别在于:
char *p="boa";
p
是指针。您正在p
指向无法修改的字符串文字"boa"
,当您尝试修改它时会发生段错误。
int i=300;
char *p=(char*)&i;
i
是int
类型的变量,您只需使用常量300
来初始化i
并执行300
值的按位副本进入i
的位置,但是从不指向常量本身,只是将其用作初始化程序。这是差异,第一个示例中的p
指向常量字符串文字,而在第二个示例中,它指向int
类型的变量。因此,稍后使用指针i
修改p
的位置很好,因为您正在修改非常量对象i
。