在C ++代码中使用C表达式是一种好习惯吗?


19

尽管我确实比班级领先,但我们还是从今年开始在学校学习C。在班级是C的基础上,我学习了Java,C ++和C。无论如何,我一直在记录自己,读书,文章,我问我的老师为什么我应该学习C,她说这是C ++的基础。刚开始编程时,我发现C ++容易得多,后来又学习了C。但是在书中,您可以看到C代码可以在C ++中运行,但反之则不行。

我的问题很简单〜在C ++中使用C表达式是一种好习惯吗?让我给你举个例子:

该代码应

#include <stdio.h>
#include <iostream>

int main() {
int x;
scanf("%d", &x);
cout << "The number you entered is " << x << "And it's double is " << x*x;
return 0;
}

在任何方面都比这更有效率或更好:

#include <iostream>

int main() {
int x;
cin >> x;
cout << "The number you entered is " << x << "And it's double is " << x*x;
return 0;
}

我已经在一些尘土飞扬的旧书中对此进行了一些简单的文档编制,从我的发现中,使用scanf而不是cout还会刷新流或类似的内容,所以我基本上是在问使用scanf和在其中使用是否更好什么背景。

这也适用于文件IO,因为我一直发现在C中,文件IO比在C ++中更容易。这个问题几乎适用于C中应用于C ++的每个通用表达式。同样值得注意的是,我使用的是现代编译器,但这并不重要,因为我在问在C ++代码中使用C表达式是否是一种良好的编程习惯。

这样做可能有利弊,但我只是在寻找是/为什么,否/为什么类型的答案。

另外,如果有任何细节,我没有发表评论。


12
混合stdio和混合时要小心iostream。一个家庭中有一定的顺序和同步保证,不一定在其外部适用。
David Thornley,2012年

感谢您的提示,但是该代码段只是一个纯示例。不管怎么说,还是要谢谢你。
Bugster

25
如果您正在学习编程;您必须学习适当的缩进!
bitmask '02

5
scanf()不是一个很好的例子;使用它非常容易出错,我建议您在C或C ++中避免使用它。
罗素·博罗戈夫

1
可能只是示例代码,但是David的评论确实成为了为什么在C ++编程时应该使用C习语的问题的核心。它们是完全不同的语言。不要比使Java和C或C ++和Visual Basic混淆更多。
科迪·格雷

Answers:


36

不,这是个坏习惯。当您以此为生时,您可能最终会违反团队所遵循的样式指南(或至少在代码审查期间受到重创)。

是的,它可以工作,但是如果有等效的c ++,请使用它。(例如,尽量不要与混合printfs使用couts


+1-短路并指向重点。这凸显了我的回答的重点:团队准则有助于将人们聚集在一起并统一他们,以便他们可以一起工作。
jmort253

此评论几乎可以正确回答我的问题,并提出了扎实的论据。谢谢。
Bugster

1
@ThePlan谢谢。每个人对于这个问题都有很好的答案。
jglouie 2012年

1
注意:printf持续使用与持续使用一样有效cout。唯一的问题是将它们和样式混合在一起。
user253751 2014年

您可以举一个C语言中没有C ++等效功能的示例吗?
klutt

20

通常,将C和C ++视为两种完全独立的语言。因此,在C ++程序中使用C语法可能被认为是不好的形式。

你是对的; 但是,该C代码可以正常编译。这实际上取决于贵公司在遵循标准方面的灵活性。如果在面试中有人问过我这个问题,我一定会让面试官知道C在C ++中工作,而且C和C ++是两种不同的语言,除非有非常非常这样做的充分理由。

要考虑的另一件事是,标准可以帮助创建一个平台,使更多的人可以轻松地使用代码。虽然您很幸运有一位老师鼓励您学习C,但是并不是每个人都那么幸运。因此,在C ++程序中混合使用C可能会使从未学习过C的人感到困惑。

总之,仅仅因为您可以做某事并不意味着您应该做,并不仅仅因为您不应该做某事就意味着您不能做:)


我知道了。功能如何?C语法比C ++语法好吗?
Bugster

10

C ++在设计上与C向后兼容,因此通常 C语言将由C ++编译器编译就可以了(通常是因为C ++中存在一些其他保留字,这些保留字不在C中,并且可以用在破坏编译的C代码中)。

但是,我认为这是混合代码的不良做法。如果您使用scanf-使用printf,如果您使用operator >>-使用operator <<。原因是重载的C ++运算符可能封装了您不知道的功能,并且不匹配它们会导致您的程序执行您不希望执行的操作。

没有特别的理由在C ++代码中偏爱C语法,因为它们是不同的语言,并且在C ++代码中使用C语法时-您仍在编写C ++代码,只是不使用其许多强大的工具。


5
C和C ++之间的不兼容性不仅仅是关键字。键入系统发生了变化,并且C中存在某些功能(尤其是C99),而C ++中不存在。(例如,可变长度数组)。
Arafangion'2

9

如果撇开编码风格和美学问题,在C ++代码中使用C时还会遇到各种技术问题:

  • 什么是C?C90,C99或C11?根据所使用的C标准,可能存在各种兼容性问题。布尔类型,//注释,C99功能(如VLA,指定的初始化程序等)。

  • C ++具有比C更严格的类型。为了在C ++中编译C代码,您很可能必须添加各种类型转换以获取期望的类型。这意味着您可能必须重写完美的,具有生产质量的C代码,才能使其在C ++中运行。

  • 通常,通过更严格的输入强制进行类型转换只是一件好事,但在某些情况下,它们可能会引入或隐藏错误。以臭名昭著的malloc()结果转换为例。这应该在C ++中进行类型转换,但决不能在C中进行。(1)

  • 混合使用C和C ++功能会导致错误和不确定的行为。例如,使用malloc()分配和使用delete释放将不起作用。(2)

  • 线程安全问题。C标准库不是线程安全的。标准的C ++库可能是线程安全的,也可能不是线程安全的,那么,将C库函数调用添加到代码中将破坏它。

    作为Windows程序员的补充说明:当Windows API CreateThread()函数用于与C库相同的程序中时,Visual C ++编译器在相当长的时间内存在一个漏洞。(3,4)

  • 在某些编译器上,调用约定可能是个问题,迫使编译器extern "C"必须明确地指出应与“ C调用约定”链接的函数。

  • 烦人的细节。逗号运算符的行为有所不同。C99 / C11中允许在struct / enum声明中尾随逗号,但C ++不允许。各种变量和函数的范围被不同地对待。等等

可能还有更多的情况。


参考文献:

  1. http://c-faq.com/malloc/cast.html
  2. http://www.parashift.com/c++-faq-lite/freestore-mgmt.html#faq-16.3
  3. http://www.flounder.com/badprogram.htm#CreateThread
  4. http://msdn.microsoft.com/zh-cn/library/windows/desktop/ms682453%28v=vs.85%29.aspx

7

C ++可以编译C的原因仅是为了“向后兼容”(避免重写现有的工作代码)。

但是C ++与c有不同的哲学方面。将它们混合在一起并不能很好地服务于它们两个。

C和C ++管理I / O的方式可能依赖于管理I / O内部状态的另一种方式。因此-至少-始终使用输入和输出。

并且在C ++程序中尊重C ++风格(除非特别要求在其他地方执行)


5

我要说,恕我直言,首先学习C是个好主意。这样,人们便开始了解为其编写软件的硬件。

混合使用这两种语言并不是必要的好主意。因为您会遇到C ++的疯狂复杂性,再加上C常见的原始位旋转。

如您所见,即使在像您这样的简单示例中,也存在不同类型的流和内部缓冲的同步问题。而且,C&C ++方法也没有任何灵活性。切换到类x,并且没有运算符可以使用流式传输和填充。

情况很复杂...

我真的认为,优秀的C ++程序员应该知道如何在每个结构后面翻转位,以及隐藏的行为是什么。

但是学习C ++(至少占其中的50%以上)需要5年以上的专业编程经验,而您却无法在长达6个月的课程中拥有20个小时左右的实践经验来进行管理。

如果我要在C中使用C ++构造,那么我就不会使用流,它们是从鸟瞰图简化的方法,并且使人们相信软件开发是容易的,但是隐藏了许多复杂性却在许多情况下没有很多好处。

但是,RAII包装器类,模板,重载,常量正确性和用于公共接口的纯抽象类(请在这里不要使用f-ng Java方式!)是不错的选择。因为它们增加了安全性,通用性和易用性,这对于现实生活中的项目非常重要。不过,请务必记住一些有关虚拟破坏,默认副本构造的爆炸性,运行时开销,常量正确性等方面的信息。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.