0

当我声明并运行以下命令时,它给了我一个分段错误

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);
}

这背后的原因是什么?上述规则是否也适用于此?

4

3 回答 3

3

这取决于您对“工作正常”的定义。但是赋值没有分段错误的原因是因为p指向i变量的地址,这显然不是一个常量。i被分配了一个常数值,但i它本身不是一个常数。

对于i = 300(假设 little endian x86):

  +--+--+--+--+
i:|2c|01|00|00|
  +--+--+--+--+
  .
 /|\
  |

p:&i

*(p+1) = 'y'

  +--+--+--+--+
i:|2c|79|00|00|
  +--+--+--+--+
  .
 /|\
  |

p:&i

因此,打印语句恰好,y为您打印,但这只是因为您依赖于平台的字节顺序(这2c是一个可打印的ASCII字符)。在大端机器上,和/或如果它是非 ASCII 的,情况可能会有所不同。

于 2012-07-28T08:34:48.570 回答
1

区别在于:

char *p="boa";

p是一个指针。您正在指出无法修改p的字符串文字,并且当您尝试修改它时会发生段错误。"boa"

int i=300;
char *p=(char*)&i;

i是类型的变量int,您只使用常量300来初始化i并将 的值按位复制300到 的位置i,但您永远不会指向常量本身,只是将其用作初始化程序。这就是区别,p在您的第一个示例中,它指向一个常量字符串文字,而在您的第二个示例中,它指向一个 type 的变量int。因此,i稍后使用指针修改位置就可以了,p因为您正在修改非常量对象i

于 2012-07-28T08:41:31.613 回答
1

好家伙...

由于字符串存在const(你说得对),第一个 seg-faults 。然而,第二个是对指针语义的迷人滥用!;-)

这是您在第二个示例中所做的事情:

  • 有一个int带有值的随机数(在你的情况下 - 300
  • 获取它的地址int- 基本上是一个地址到一个包含int300 (32位?)的位置并将其转换为 a char*,其中每个元素都指向一个 8 位值
  • 获取“第一个”8 位值的地址,递增 1(递增 8 位(!))并将这 8 位的值更改为数字 ASCII 代码“y”
  • 打印“结果字符串”
于 2012-07-28T08:36:37.153 回答