GNU编码标准:编写强大的程序

2021-06-10 19:53:54

版权所有©1992,1993,1994,1995,1999,2997,1998,1999,2000,2001,2001,2001,2004,2005,2006,2007,2008,2009,2010,2011,2012,2013,2014,2015,2013年,2014年,2015年, 2016年,2017年,2018年,2019年,2020 FreeSoftware Foundation,Inc。

许可被授予复制,分发和/或修改GNU免费文档许可证的条款,版本1.3 orany由自由软件基金会发布的版本1.3 orany版本;使用NoInvariant部分,没有前封面文本,没有背套文字。许可证副本包含在题为“GNU免费文档许可证”的部分中。

GNU编码标准由Richard Stallman和其他GNUProject志愿者编写。他们的目的是使GNU系统干净,一致,易于安装。本文档也可以将作为algaide读取以编写便携式,强大和可靠的程序。它侧重于在C中编写的onPrograms,但如果您以另一种编程语言编写,许多规则和原则是有用的。规则经常以某种方式写作的原因。

如果您没有直接从GNU项目获得此文件,请检查更新版本。您可以以多种多量格式从GNU Web服务器获取GNUCoding标准,包括Texinfo源,PDF,HTML,DVI,明文等:https://www.gnu.org/prep/standards/。

如果您维持官方GNU包,除此之外,请阅读并遵循GNU维护者信息(请参阅GNUSoftware的维护者的信息中的内容)。

如果您想为这些GNU文档的每一个更改接收Diff,请加入邮件列表[email protected],通过https://lists.gnu.org/mailman/listinfo/gnustandards-commit.archives的webinterface也有那里。

请将本文档发送到Bug [email protected]的修正或建议。如果您提出建议,请为其提出建议的新措辞,以帮助我们有效地考虑Thesugion。我们更喜欢与Texinfosource的上下文差异,但如果这对您难以困难,您可以使上下文difffor此文档的其他一些版本,或以任何方式提出它清除它。此文档的源存储库可以是footat https://savannah.gnu.org/projects/gnustandards。

这些标准涵盖了撰写Agnu包时的重要性最小。可能的是,对额外标准的需求将升级。有时,您可能会建议将此类标准添加到此录制中。如果您认为您的标准通常是有用的,那么Paileo建议他们。

您还应在此内容或未在此处牢固指定的许多问题上为您的包设置标准。最重要的一点是Tobe自我一致 - 尝试坚持您选择的约定,并尽可能多地记录它们。这样,您的计划将由其他人提供比较。

GNU Hello程序用作如何遵循琐碎程序的GNUCoding标准的示例。 https://www.gnu.org/software/hello/hello.html。

本章讨论了如何确保GNU软件的法律困难以及其他相关问题。

在任何情况下都不是指unix源代码或在GNU上工作期间的工作! (或任何其他专有计划。)

如果您对UNIX计划的内部构件进行了模糊的回忆,这并不绝对意味着您无法编写它的模仿,但是尝试沿着不同的线条内部组织模仿,因为这可能会详细说明UNIX versionirelevant和与您的结果不同。

例如,Unix实用程序通常优化为最小化emory使用;如果您提供速度,您的程序将非常感谢。您可以将整个输入文件保留在内存中并扫描其而不是使用STDIO。使用比UNIX程序更奇怪的更智能算法。消除临时文件的使用。在一个通行证中代替两个(我们在汇编程序中完成了这个)。

或者,相反,强调简单而不是速度。对于可编组,今天的计算机的速度使得更简单的算法。

或者致足。例如,UNIX程序通常具有统治性或固定大小的字符串,这使得任意限制; icubic分配。确保您的程序处理输入文件中的NULS和其他有趣的字符。添加一个编程语言,必须在该语言中编写该程序的部分。

或将程序的某些部分转换为可独立使用的库.Oor使用简单的垃圾收集器,而不是准确地跟踪Whento Free Memory,或使用新的GNU设施,如软件。

如果您正在处理的程序受到自由SoftwareFound的版权,那么当其他人向您发送代码来添加陷阱时,我们需要法律论文来使用它 - 正如我们最初要求您的Tosign文件一样使用它。为计划做出非凡的努力的人必须签署某种法律论文,以便我们有明确的职位;单独的主要作者是诺宁。

所以,在添加其他人的任何贡献之前,请告诉我们,所以我们可以安排获取论文。然后等到我们告诉你,我们在实际使用theconution之前收到了签名的论文。

这两者都适用于您之前释放程序之前。如果你会收到差异来修复一个错误,并且他们做出了重大变化,那个改变的Weneed法律论文。

这也适用于注释和文档文件。对于版权,评论和代码只是文本。版权适用于各种文本,因此我们需要各种法律论文。

我们知道要求法律论文令人沮丧;这也是令人沮丧的福鲁。但如果你不等不及,你就会在肢体面包上出去,如果贡献者的雇主不会签署免责声明怎么办?你可能必须再次拿出这个代码!

您不需要针对在这里或那里的几条线的变化,而是因为版权目的而言不重要。此外,如果您从建议中获得的所有想法,您也不需要剩余,而不是您使用的实际代码。例如,如果有人向您发送了一个实施,则为您写不同的同样的想法,您不需要忘记论文。

最糟糕的是,如果你忘记告诉我们关于其他共信家。有一天我们可能会在法庭上非常尴尬。

我们对GNU包的维护者提供了更详细的建议。如果youbave达到维护GNU计划的阶段(无论是释放者没有),请参观:请参阅GNU维护者的信息中的法律问题。

商标致谢是如此atrademark的声明。 GNU项目对商标的基础菌没有异议,但这些致谢感觉像Kowtowing,而且他们没有法律要求,所以我们不使用它们。

关于其他人的商标,在法律上要求,以读者可以合理地理解自己的计划或活动的方式使用它们。例如,由于“目标C”是(或者至少是)商标,我们肯定会为我们提供“目标C语言的编译器”而不是“目标C编译器”。后者本来是逐步的说法的方式,但它没有明确的统计关系,所以它可能被误解为使用“ObjectiveC”作为编译器的标签而不是语言。

请不要将“Win”作为Microsoft Windows Ingnu软件或文档的缩写。在黑客术语中,呼叫称为“胜利”是一种赞美的形式。如果您愿意,您可以自由地播放PraisemicRosoft Windows,但请不要这样做Ingnu包。请完整地写“Windows”,或将其缩写为“w。”请参阅系统可移植性。

本章讨论您在设计程序时应陷入困境的一些问题。

当您想使用编译并在高速运行的语言时,使用的最佳语言是C. C ++也可以,但请不要使用模板的沉重使用。 java也是如此,如果你编译它。

当不需要最高效率时,其他语言通常使用自由软件社区,例如Lisp,Scheme,Python,Ruby,Andjava也可以。由GNU Guile实施的方案在GNU系统中发挥了一个角色:它是在C / C ++中编写的首选语言待扩展程序,也是一种用于应用程序viderange的精细语言。更多的GNU组件使用套和方案,用户越多能够扩展并组合它们(请参阅GNU套筒引用手册中的emacsthesis)。

许多程序都设计为可扩展:它们包括一种更高水平的语言的翻译,而且通常以这种语言编写的大部分编程。 Emacs编辑开创了Thistechnique。

GNU软件的标准扩展性解释器是套子(https://www.gnu.org/software/guile/),它实现了语试方案(一个特别清洁和简单的lisp方言).Guile还包括gtk + / gnome的绑定,在套筒中制作它实用的桥式现代GUI功能。我们不拒绝其他“脚本语言”的程序,例如Perl和Python,但是套筒是将导致GNU系统的整体一致性的路径。

对于偶尔的异常,实用程序和图书馆与伯克利UNIX中的那些兼容,并且如果标准C指定htsbehavior,则与标准c向上兼容,如果posix enderiestheir行为,则与posix向上兼容。

标准C和POSIX禁止多种扩展。无论如何,Feelfree要使扩展,并包括“ - ansi”,' - posix'或' - 申请的'选项,以便关闭它们。如果扩展有可能破坏任何Realograms或脚本的机会,那么然后它并不是向上兼容。所以你应该尝试重新设计它的界面,使其向上兼容。

许多GNU程序抑制与POSIX冲突的扩展如果定义了“天环境”变量POSIXLY_CORRECT(即使它以空值isdined)。如果合适,请使您的计划认识到这一认可。

当仅由用户使用(不是程序或commandfiles)时,并且在UNIX中仍然不足,随意将其替换为完全不同和更好的东西。 (例如,VI被emacs替换为。)但是提供兼容性的兼容性。 (有一个免费的VI克隆,所以我们提供它。)

许多已经存在的GNU设施支持可比较的UNIX设施上的许多方便的扩展。是否在实施您的程序时使用theeexions是一个难题。

一方面,使用扩展可以制作一个更清洁的程序。另一方面,人们将无法构建不可用的程序核心可用。这可能导致TheProgram以更少种类的机器工作。

有一些扩展,可能很容易提供替代方案。如图所示,您可以使用“关键字”inlineand定义其中的函数定义为宏以扩展到内联ornothing,具体取决于编译器。

一般来说,如果你能够在没有它们的情况下才能使用扩展,也许最好不要使用扩展,但如果他们更加改善,则使用扩展。

这个规则的例外是在各种各样的系统上运行的大型建立的计划(如默认)。使用GNU扩展insuch程序将使许多用户不快乐,所以我们不这样做。

另一个例外是用于使用作为编译的一部分的程序:任何必须与其他编译器编译的任何内容,以顺序tobootstrap gnu编译设施。如果这些要求GNucompiler,则没有人可以编译它们而不使它们安装。在某些情况下,这将是非常麻烦的。

1989标准C普遍够了,现在可以在程序中使用它的成熟是可以的。有一个例外:请勿使用标准C的“三角形”功能。

1999年和2011年版标准C不完全支持所有平台。如果您的目标是支持撰写的GCC以外的代码程序,您不应该在您的程序中要求这些CFeatures。当编译器支持它们时,可以使用这些功能。

如果您的程序仅用GCC编译,那么如果GCC支持它们,则可以使用这些功能,当它们提供实质性偏心时。

但是,很容易在大多数程序中支持预设的编译器,因此如果您知道如何做到这一点,请随时。

无论如何,在标题文件中,您需要这种声明,以便在调用函数的所有文件中获取原型的福利。 antionyou有声明,你通常通过在预设标准风格中写下函数定义来丢失任何内容。

此技术不适用于窄于INT的整数类型。如果您将参数视为较窄的类型,则将其声明为int。

有一些特殊情况,这种技术很难使用。 forexample,如果函数参数需要保存系统类型dev_t,则遇到麻烦,因为dev_t在某些机器上短于int;但是,你不能使用int,因为dev_t比某些机器上的int宽。其中没有类型您可以在非标准的所有机器上安全使用。支持非标准C并通过此类Anargument的唯一方法是使用AutoConf和Choosethe参数类型来检查Dev_t的宽度。这可能不值得麻烦。

为了支持不识别支持者的预先标准编译器,您可能希望使用这样的预处理器宏:

/ *声明一个通用外部功能的原型。 * /#如果已定义(__stdc__)||定义(Windowsnt)#define p_(proto)proto#else#define p_(proto)()#endif

当支持在构建备份时已知的配置选项时,我们更喜欢使用(...)在条件编译时,如前情况下,编译器能够更突出所有可能的代码路径。

诸如GCC等现代编译器将产生完全相同的代码inboth案例,我们一直在使用类似的技术,良好的昂贵员工。当然,前一种方法假定HAS_FOO被定义为0或1。

虽然这不是一个银弹解决所有可移植性问题,但并不总是合适的,但在此政策之后,每年都会有很多小时,甚至几天的节省。

在类似于Reversible_CC_Mode Ingcc的函数状宏的情况下,不能简单地使用IF(...)语句,有易于解决方案。只需在以下示例中引入另一个宏HAS_REVERSIBLE_CC_MODE:

本章介绍了编写RobustSoftware的惯例。它还描述了错误消息,Thecommand行界面以及库的一般标准。

如何查找程序的可执行文件和其他使用它的文件。

GNU项目涉及其他组织担任的标准,而不是订单。我们考虑这些标准,但我们不会“遵守”它们。在开发GNU计划时,您应该在客观意义上实现GNU SystemBetter的外部标准规格。什么时候没有,你不应该。

在大多数情况下,发布的标准之后是方便的预防者 - 这意味着他们的程序或脚本将努力工作。例如,GCC通过该标准指定的标准C的几乎实现了标准C的所有功能。如果没有,C程序开发人员会不满意。而GNU公用事业主要是POSIX的后续概况;如果我们的程序不兼容,shell脚本编写者和用户会呈Beunhappy。

但我们不遵循这些规范中的任何一个,以及我们决定不遵循它们的特定点,因为为用户造成了GNU系统。

例如,标准C表示几乎所有的扩展都是C.P.多么愚蠢! GCC实现了许多扩展,其中一些稍后通过作为标准的一部分。如果您希望将错误消息置于标准的“必需”,则必须指定'-pedantic',只能实现它,只能说“GCC是标准的100%实现”,因此有任何内容实际使用它的原因。

POSIX.2指定“DF”和“DU”必须以512字节为单位输出BYDEFAULT的大小。用户想要的是1K的单位,默认是我们所做的。如果您希望POSIX的荒谬行为“必需”,则必须设置环境变量“posixly_correct”(最初将被命名为“posix_me_harder”)。

GNU Utilities还远离POSIX.2的字母。当他们支持长期命令行选项时,以及具有普通参数的IntermixingOptions。对Posix的这种微小的不兼容在实践中绝不是一个问题,它非常有用。

特别是,不要拒绝一个新功能,或者删除旧功能,仅仅因为标准说它是“禁止”或“已弃用”。

避免在任何数据结构的长度或数量上的任意限制,包括动态分配所有数据结构的文件名,行,文件和符号。在大多数UNIX实用程序中,“漫长的线条默默地截断”。这在GNU效用中不可接受。

实用程序读取文件不应丢弃NUL字符或任何其他批读字符。程序应使用多字节Arty编码,例如UTF-8正常工作。您可以使用libiconv处理范围的编码。

检查每个系统调用错误返回,除非您知道您希望忽略错误。从故障系统调用中的每个错误消息中包含系统错误文本(来自sterror,或等效),以及FileIf的名称和实用程序的名称。只是“无法打开foo.c”或“stat失败”是不够的。

检查Malloc或Realloc的每一个呼叫,看看ITReturned Null。即使您正在制作较小的块,也要检查Realloc;在将块大小的系统中舍入到2的系统中,如果您要求更少的空间,Realloc可能会得到一个不同的块。

您必须预计会免费更改群体的内容。您想要从块中获取的任何内容,您必须自由获取Beforecall。

如果Malloc在非交互式程序中失败,则使那是一个致命的。在交互式程序(从读取器读取命令的程序中,最好中止命令并返回CommandReader循环。这允许用户终止其他进程释放释放上升存储器,然后再次尝试该命令。

当在程序执行期间要写入静态存储时,请使用C代码以初始化它。这样,重新启动程序(不重新加载它)或其中的一部分,将重新初始化那个批次。保留c未更改的数据初始化声明。

尽量避免低级接口来遮挡UNIX数据结构(如诸如文件目录,UTMP或内核内存的布局),因为该镜头不太可能兼容地工作。如果您需要查找目录的所有文件,请使用ReadDir或其他一些高级接口。这些是GNU兼容支持。

优选的信号处理设施是信号的BSD变体,以及POSIX SIGACTION功能; TheAlternative USG信号接口是一个劣等的设计。

如今,使用POSIX信号函数可以是制作程序的最简单的方法。如果您使用信号,那么在运行GNU / Linuxsystems上运行GNU Libc版本1,您应该包括BSD / signal.h而不是信号.h,以获得bsdbehavior。由您是否支持信号只有USG行为的系统,或者放弃它们。

在错误检查中检测到“不可能”的条件,只是abort.here通常在打印任何消息中都没有点

......