【问题标题】:%s format specifier in printfprintf 中的 %s 格式说明符
【发布时间】:2012-12-02 05:09:03
【问题描述】:
#include <stdio.h>
int main()
{
    char str[11] = "HelloWorld";
    printf("%s\n",str);
    printf("%s\n",str+3);

    /* This Line here is the devil */
    printf("%s\n",str[2]); // %s needs an addr not a value.

    return 0;
}

为什么该行会出现分段错误。是因为printf 中的%s 需要地址而不是值。 真正的原因是什么??

【问题讨论】:

  • 你给了它一封信而不是地址。所以它会尝试访问地址“0x6c”(“l”的十六进制),这几乎可以肯定是一个无效地址。
  • 因此访问该内存位置可能会被证明是非法的,因此会出现分段错误.. OK..
  • @Bhargav:格式说明符与传递给printf 的实际类型不匹配会导致未定义行为,这就是您的示例所做的。
  • 如果有可疑原因,您可以尝试将其删除并自己查看。为答案 +1 以获得很好的解释。

标签: c segmentation-fault printf


【解决方案1】:

str[2] 返回一个字符,而不是指向字符的指针。因此,printf 将尝试从地址0x6c 开始阅读。在那里,0x6c 很有可能是一个无效地址,会导致段错误。但是,如果它不是无效的,那么 printf 将继续读取,直到它到达一个 0x00 字符,这很可能进入一个无效的地址范围。

如果您想准确了解为什么会出现段错误,则需要在调试器中进行操作,这可能很有趣且具有教育意义。

如果你想修复崩溃的线路,你可以将其更改为:

  printf("%s\n", &str[2]);

我认为这种风格比str+2 更好。

【讨论】:

  • 我已经知道的最后一个建议.. 我知道这是错误的,但就是无法弄清楚段的确切原因 :)
  • 第二句描述了一种可能实现的一种可能行为,但没有根本原因它是正确的。正确的答案只是 OP 破坏了接口契约(%s 需要在相应的参数位置指向 char 的指针),因此行为未定义。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2017-11-16
  • 2012-05-17
  • 2012-05-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-05-14
相关资源
最近更新 更多