Stack Overflow上有一些非常有经验的人,他们总是谈论C标准。人们似乎不喜欢非便携式解决方案,即使他们为我工作。好的,我知道需要遵循该标准,但是它不会给程序员的创造力带来束缚吗?
遵循标准有什么具体好处?特别是因为编译器可能会稍微不同地实现标准。
Stack Overflow上有一些非常有经验的人,他们总是谈论C标准。人们似乎不喜欢非便携式解决方案,即使他们为我工作。好的,我知道需要遵循该标准,但是它不会给程序员的创造力带来束缚吗?
遵循标准有什么具体好处?特别是因为编译器可能会稍微不同地实现标准。
Answers:
坚持标准是一件好事,有几个原因。
被锁定在编译器中很难。您完全由一群拥有自己议程的开发人员所左右。它们显然并不能解决您的问题,但是如果您的编译器开始滞后于优化,新功能,安全修复等,那就太糟糕了;你被困住了。在极端情况下,一些公司必须开始修补他们依赖的任何工具。当有其他工作工具时,这是巨大的金钱和时间浪费。
被锁定在平台上会更难。如果您在Linux上开发软件并想切换到Windows,因为您意识到自己的市场确实存在,那么您将有一点时间更改代码中的每个非便携式黑客,以使其发挥出色同时使用GCC和MSVC。如果您的核心设计有几个类似的基础,那么祝您好运!
向后不兼容的更改最困难。该标准永远不会破坏您的代码(忽略python)。但是,一些随机的编译器作者可能会决定,确实不值得为此麻烦的特定附加组件,因此放弃它。如果您碰巧依赖它,那么您将停留在最后使用的任何过时的旧版本上。
因此,遵循标准的首要信息使您更加灵活。您的语言肯定会更有限,但您的语言会更多
这是一个微妙的平衡,但是完全忽略该标准绝对是一个错误。我倾向于组织我的C代码以依赖可能以非便携式方式实现的抽象,但是我可以透明地移植而无需更改依赖抽象的所有内容。
该标准是您与编译器之间的一种“合同”,它定义了程序的含义。作为程序员,我们经常对语言的工作方式有一个确定的思维模式,而这种思维模式通常与标准不符。(例如,C程序员经常将指针视为大致“表示内存地址的整数”,因此,假定对可能使用表示内存的整数执行的指针执行任何算术/转换/操作是安全的。这个假设与标准不符;实际上,它对指针的操作施加了非常严格的限制。)
那么,遵循标准而不是您自己的心理模型有什么好处?
简而言之,那就是标准是正确的,而您自己的思维模式是错误的。您的思维模型通常是简化的视图,说明在通常情况下禁用所有编译器优化后,事情如何在自己的系统上运行;编译器供应商通常不努力遵循它,尤其是在优化方面。(如果您不履行合同的最后期限,则您将无法期望编译器发生任何特定行为:垃圾回收,垃圾回收。)
人们似乎不喜欢非便携式解决方案,即使他们为我工作。
最好说“即使他们似乎为我工作”。除非您的编译器专门记录了给定的行为将起作用(即:除非您使用的是由标准的适当的标准加上编译器文档组成的丰富标准),否则您将不知道它确实有效,或者它确实可靠。例如,有符号整数溢出通常会导致在许多系统上进行包装(因此INT_MAX+1
通常是INT_MIN
)-除非编译器“知道”有符号整数算术永远不会在(正确的)C程序中溢出,并且经常基于此“知识”。
-fwrapv
,然后使用略有不同的非标准语言,该语言总是包裹有符号整数算术。
我了解需要遵循该标准,但是这是否会给程序员的创造力带来束缚?不同的编译器遵循标准的方式仍然存在一些差异。例如,我可以编写一个行之有效的代码,在性能和速度上都非常好,即所有方面都很重要,但仍然不一定严格遵循标准。
否。标准告诉我们可以做什么。如果未指定,则您处于未定义的行为范围内,然后所有选择都关闭了-该程序可以自由执行任何操作。
由于您提到了void main()
vs的特定示例int main()
,因此我可以改善答案。
void main()
不是主要功能的标准声明。它可以通过扩展在某些编译器上工作,但它依赖于实现。即使工作正常,也必须检查它是否满足您的要求。问题是,编译器开发人员可能决定void main()
在下一个编译器版本中删除它,从而破坏您的应用程序。
另一方面,该标准明确定义了main as的签名,int main()
并说明了应该做什么。
另一方面,有些东西没有在标准中定义。然后,可以应用另一个标准(例如POSIX)。最好的示例可能是在c ++ 03中实现线程,因为c ++ 03标准程序是1线程的。在这种情况下,您将不得不使用依赖于平台的库或诸如boost之类的东西。
如果您的项目是关于特殊项目的,则不要遵循规则,例如gov项目或军方项目,但是如果您是在谈论开源或具有分布式团队的大型项目,则需要遵循规则。