我需要学习C吗?

计算科学 Python C++ 教育 职业发展
2021-11-25 09:07:11

我是科学计算专业的博士生,在过去的几个月里,我花了很多时间以正确的方式学习 Python 和 C++。我觉得我已经很好地学习了 C++,如果我身边有一本好的参考书,我可以使用 Python 做我想做的事。

我也足够了解 MATLAB,可以对我的想法进行原型设计并获得解决方案。(如果我厌倦了编写 Python 代码,这是我的首选)。

我在这里多次读到应该将 C 和 C++ 组合成一个“C/C++”,因为它们是截然不同的语言,有着不同的动机,我完全同意这种观点。

虽然我不能声称“知道” C++,因为我一直在学习,但我认为我知道我应该如何使用它以及我不应该如何使用它。我学的第一门语言是 C,但距离我上次使用它已经很久了。我的问题本质上是这样的:

鉴于我了解 MATLAB、C++ 和 Python;我应该花时间学习C吗?我对上述 3 种语言的了解是否足以让我编写代码?

我的研究更多是在数值线性代数方面,但我也做一些离散事件模拟/随机过程咨询。我的目的是在工业界工作(我的顾问建议我学习 C++,这样我就可以继续工作,尽管他对语言没有个人偏好)。

4个回答

我将只讨论 C 与 C++ 的比较。虽然用 C 编写的任何东西都可以通过一些语法修饰移植到 C++,但社区有不同的价值观。C 库社区比几乎任何其他社区都更重视二进制稳定性。二进制稳定性对于低级库至关重要,以避免对上面的那些层造成持续的痛苦,尤其是在与二进制分发模型和共享库一起使用时。C 是此类库的压倒性偏好,这些库只需要工作,能够发布新版本而无需重新编译上面的层。

可以发布在此级别运行的 C++ 库,但您最终需要“用 C++ 编写 C”。例如,您永远不会将具有私有或虚拟成员的结构定义放在公共标头中,您永远不会在公共接口中使用模板,并且您永远不会拥有基于从具有任何数据成员的类继承的 API。这些约束是精确包含依赖项所必需的,这样您就可以在不更改二进制接口的情况下修改您的实现。由于其更简单的对象模型和明确定义的 ABI,C 往往更容易从不同的语言绑定。

如果您在应用程序级别而不是库级别编写代码,那么您的二进制接口并不重要,因此许多这些问题都消失了。使用继承和模板等 C++ 语言特性仍然倾向于生成更紧密耦合的代码,随着项目的增长,导致重新编译更加耗时。除了更庞大的编译时依赖关系之外,简单地使用 C++ 编译器编译 C 代码会显着增加编译时间(对于大多数工具链来说大约是 2 倍)。

如果您对这些问题感兴趣,或者如果您打算在较低级别的库上工作,那么花时间在 C 上可能是值得的。如果您喜欢使用 C++ 语言特性,并且不太为二进制接口和耦合紧密性所困扰,那么这可能不是一个很好的时间利用方式。但是,如果这些事情将来开始困扰您,请记住 C。

与其“学习 C”,我建议你现在已经完成了足够多的编程并使用了足够多的编程语言,你应该专注于提高你的编程技术和更广泛的计算机科学知识。然后在特定项目需要时学习 C。

经验丰富的程序员可以根据特定项目的需要快速掌握新的编程语言。他们可以做到这一点,因为他们理解从一种语言转换到另一种语言的重要概念——如果你掌握了那些更高层次的概念,语法就不是什么大问题。当您看到学生尝试学习他们的第二种编程语言时,您经常会看到他们在理解一些不属于他们的第一语言的新概念时遇到了困难。例如,从 Fortran 开始的学生经常在 C 语言中遇到指针问题。了解 C 的学生经常在 C++ 的面向对象特性中遇到问题,等等。

这个问题的答案真的取决于你真正做了什么。

作为一名从事高性能计算的计算机科学家,我想说了解/理解 C 语言编程至关重要。

但是,如果您只是在计算机上做事那么您的 C++ 知识应该足以让您通过。

更具体地说,如果您真的对计算方面感兴趣,即编写充分利用现代计算机的算法,您将无法避免处理内存管理、数据布局、SIMD 等低级方面矢量化、指令级并行、共享内存并行或 GPU 计算(CUDA 和 OpenCL 基于 C)。

现在,大多数这些事情都可以由编译器(例如,用于内存管理、数据布局、矢量化)和/或更高级别的抽象(例如 OpenMP、OpenACC、优化库)来处理。但只是在一定程度上。手工做事通常需要更多的工作,但回报可能是性能的一个数量级。

基本上,每当您想自己控制细节时,通常最终都会使用 C,因为它“更接近金属”。然而,问题是,这是真正想要的吗?

我对这个问题的回答有一些复制粘贴,还有一些额外的细节。

我在使用弱嵌入式处理器(想想手机处理器)的工业(测量和机器控制设备制造商)工作,其中大约 50% 的计算任务用于数字计算——主要是传感器融合工作。

我们有一位曾经在 HPC 小组工作的数学家为我们工作,所以这是您最终可能找到工作的奇怪地方之一!

在这种环境中,您几乎肯定会拥有一个操作系统(例如 Linux、QNX、WinCE),C++ 才是王道。我们仅将 C 用于内核工作(即设备驱动程序)和没有操作系统的深度嵌入式工作(8 位微控制器)。我们不将 C 用于任何数字工作。事实上,我们的平台没有 FORTRAN 编译器!

高性能对我们很重要,因为我们只有一个 1 瓦的 CPU 用于处理。虽然我们没有一些并行性的“迷人”问题,但我们必须了解缓存和内存,并且越来越需要了解 SIMD(想想NEON)。更重要的是,与 HPC 不同,我们必须敏锐地意识到延迟(这是机器控制!)和其他操作系统方面,如调度和上下文切换。在这种环境下,内存分配特别讨厌,因为它几乎肯定意味着上下文切换(== 延迟,并且在 400MHz CPU 上,时间成本很高)。

这些问题与语言的选择无关,所以我不同意@Pedro 的回答,即 C 是必要的——毕竟,在使用 C++ 时,SIMD 的编译器内在函数是可用的。但是,这确实意味着您必须非常小心使用 C++ 的哪些特性以及它们的成本。

因此,要完成答案,不,您不需要 C。我们使用 MATLAB 进行分析工作,使用 python 编写脚本,因此除了 C++ 之外,您的两种语言都是不错的选择——至少在我的行业中是这样。