【问题标题】:scanf and the p conversion specifierscanf 和 p 转换说明符
【发布时间】:2014-12-29 09:58:38
【问题描述】:

在 C11 规范中,%p 的参数类型必须是void **,以防scanf() 函数,但我不知道如何输入地址并将其存储到void **。 事实上,如果我尝试制作:

void **p;
scanf("%p", p);

我遇到了分段错误。

附: C11规范:

对应的参数应该是指向void的指针

【问题讨论】:

  • 我不明白这个scanf() 硬编码地址的实际用例是什么?你有 MC,你知道你需要将值扫描到的实际位置吗?p 是一个双指针,它应该指向一个我们在所示代码中看不到的指针。跨度>
  • @Gopi,是的,我知道,事实上我不明白为什么标准说要使用双指针!
  • 我要求您不要以某种方式更改您的问题,以免之前提交的答案看起来错误。考虑添加额外信息保持原始帖子不变。此外,当提出与特定标准相关的问题时,请使用适当的标签。

标签: c c11 format-specifiers


【解决方案1】:
void **p;
scanf("%p", p);

因为同样的原因不起作用

int *i;
scanf("%i", i);

不起作用 - 您正在写入一个未初始化的指针(或告诉 scanf 至少写入一个)。

这行得通:

int i;
scanf("%i", &i);

这也是如此:

void *p;
scanf("%p", &p);

【讨论】:

    【解决方案2】:

    注意:原始帖子未提及 c11 标准。

    好吧,根据c99 规范文档,第 7.19.6 章。 1 2,第 8 12 段,

    p

    匹配实现定义的序列集,应该是 与 %p 转换可能产生的序列集相同 fprintf 函数。对应的参数应该是一个指向 指向无效的指针。输入项被转换为一个指针值 实现定义的方式。如果输入项是之前转换的值 在同一程序执行期间,结果应比较的指针 等于那个值;否则 %p 转换的行为是不确定的。

    所以,它不是void **,而是void *

    接下来,您的分段错误的原因是在scanf() 中使用了未初始化的指针p。在使用 [将其传递给 scanf() 作为参数] 它之前,您没有为 p 分配内存。

    正如其他人的建议,您可以很好地使用类似的东西

    void *p;
    scanf("%p", &p);
    

    这里,&p 的值实际上是 pointer to a pointer to void 并且有一个定义的地址。

    【讨论】:

    • 在C11规范中说:“相应的参数应该是一个指向void的指针”
    • @xdevel2000 好吧,分段错误的原因是使用了未初始化的指针。
    • 7.19.6.1 是 fprintf,而不是 fscanf
    • @mafso 非常感谢。真的真的我应该小心点。更新了答案并进行了更正。
    • %p 甚至可以用来做什么?
    【解决方案3】:

    你没有初始化p。试试:

    void *p;
    scanf("%p", &p);
    

    这里取p的地址,有效。

    【讨论】:

      【解决方案4】:

      标准规定 %p 应该有 void * 类型参数。您需要将p 声明为void * 然后

      scanf("%p", &p);    
      

      您遇到段错误的原因是因为在void **p 中,p 没有指向任何地方。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2019-09-28
        • 1970-01-01
        • 2020-04-13
        • 2023-02-10
        • 2013-12-20
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多