“不得使用输入/输出库<stdio.h>。”

时间:2015-08-07 16:06:13

标签: c++ coding-style

我正在阅读JSF AV C++ Coding Standards,而规则22则说:

  

AV规则22(MISRA规则124,修订版)

     

输入/输出库<stdio.h> 不得使用。

有没有理由不使用<stdio.h>

我知道这些规则适用于 C ++ ,我们可以使用<iostream> ...但<stdio.h>出了什么问题?

3 个答案:

答案 0 :(得分:5)

最明显的问题是printfscanf及其各种堂兄弟(例如sprintf)缺乏类型安全。

除了类型安全问题之外,scanfsprintf系列使得确保防止缓冲区溢出变得相当困难。它可以完成,但它并不是微不足道的,似乎只有极少数的C程序员对如何处理这类任务有任何线索。

答案 1 :(得分:2)

有时会出现这样的问题,关于为什么某些编码标准要求这个或那个。

正确的答案应该始终是:无论编码标准的作者是什么意图。有时候,编码标准会给出其规则的理由;这一个显然没有。因此,我们只能猜测您的问题的答案可能是什么。

我因此加上我自己的猜测:

飞行器听起来非常严肃,具有极高的正确性和坚固性要求。 printfscanf等可以轻松编写代码,这些代码可以快速通过编译器,但在运行时会创建未定义的行为。

这些C函数对普通C ++流有一个优势:格式字符串可以更容易地编写国际化代码。考虑这个快速组成的示例,使用std::ostream来表示某个UI组件,例如客户管理应用程序中的按钮标签:

os << "Update customer\n";

您可能想要动态添加客户名称:

os << "Update " << customer_name << "\n";

您可能希望为&#34;更新&#34;动态插入外语单词:

os << InternationalString(id_update) << " " << customer_name << "\n";

然而,这本质上是以英语为中心的。它会产生正确的英文字符串,例如&#34;更新John&#34;或者&#34;更新Joe&#34;,但是例如对于具有不同语法的德语,并且需要像#34; John aktualisieren&#34;或者&#34; Joe aktualisieren&#34;,在这种情况下,动词前面有名字。

这是格式字符串闪耀的地方:

sprintf(s, FormatString(id_update_customer), customer_name);

根据应用程序的语言设置,此类FormatString功能可能会返回"Update %s""%s aktualisieren"

但是,它非常危险。事实上,如果我上面示例中的customer_namestd::string,那么您已经有了未定义的行为。

Boost.Format这样的库试图将格式字符串的灵活性与流的类型安全性结合起来。

回到你的实际问题,我的猜测是,国际字符串的灵活性并不是飞机制造业的重大关注点。

正如您所看到的,编码标准的每个方面都可以进行详细讨论。单个规则的原因可能并不总是那么明显,它们通常与编写标准的应用程序域有关。

如果您不能向作者询问编码标准,那么您的问题就无法得到真正的回答。

答案 2 :(得分:2)

这个JSF C ++标准引用了MISRA-C:1998,两者都与在安全关键系统中使用C语言有关。最新标准MISRA-C:2012已更新(提供更多理由和更好的示例),MISRA规则124现在是规则21.6“不得使用标准库输入/输出功能”。

基本原理非常简单:流和文件I / O具有与之关联的未指定,未定义和实现定义的行为。指南中还包括对C标准(C90和C99)部分的引用,其中描述了这些不可预测的行为。

如果实际实现得到很好的定义或者代码显示不重要,则可以打破规则(通过偏离过程)。