我在哪里可以找到关于“的资源?”;“现代”;C编程?

我在哪里可以找到关于“的资源?”;“现代”;C编程?,c,C,尽管读过K&R,甚至教过C课程,但我发现自己无法完全理解所谓的“现代”C 就我所知,现代编程中似乎有许多不成文的约定,在任何地方都没有记录 以SQLite源代码为例。例如,我发现: SQLITE_API int sqlite3_close(sqlite3 *); SQLITE_API代表什么?这在语法上是如何正确的 或者这个: #ifndef _SQLITE3_H_ #define _SQLITE3_H_ 在什么时候在宏前面加下划线,是否有公认的惯例?有时我看到宏的前缀是两个下划线 或者如

尽管读过K&R,甚至教过C课程,但我发现自己无法完全理解所谓的“现代”C

就我所知,现代编程中似乎有许多不成文的约定,在任何地方都没有记录

以SQLite源代码为例。例如,我发现:

 SQLITE_API int sqlite3_close(sqlite3 *);
SQLITE_API代表什么?这在语法上是如何正确的

或者这个:

#ifndef _SQLITE3_H_
#define _SQLITE3_H_
在什么时候在宏前面加下划线,是否有公认的惯例?有时我看到宏的前缀是两个下划线

或者如何使用固定大小的类型,例如
uint32
等等。什么时候应该使用这种做法,什么时候不应该?新的ish
bool
类型怎么样,什么时候应该优先于简单的int


这些是我在阅读别人的源代码时提出的一些问题。有什么地方可以帮助我回答这些问题吗?

SQLITE\u API
这样的代码很可能是预处理器定义的,它担心在DLL库构建中公开调用。这很常见

如果它在C中都是大写,那么它很可能是一个预处理器符号,一个好主意是经常通过预处理器运行游戏并读取结果

#ifndef _SQLITE3_H_
#define _SQLITE3_H_
只是为了防止多重包容


如果xxx.h包含此文件以及yyy.h,并且yyy.h也包含此文件,那么它可以防止出现错误。

我认为没有一个很好的参考来说明这些内容。您所看到的是一系列约定,其中一些在行业中使用非常广泛,另一些可能更具体到您自己的代码库中,这些约定已经出现,用于处理C(及其衍生工具)中大型软件项目中的标准挑战或情况。正如您所注意到的,K&R是一个很好的教学工具,但它并没有解决这些大型项目惯例中的任何一个,这些惯例大多是在行业内有机地出现的

你举了两个很好的例子。第一个是一个
#define
d,用于修饰函数,使其正确导出,或者只是记录要导出的函数。第二种模式称为“”(参见链接),传统的下划线是可选的,但这是避免与正常幻数定义冲突的好方法

有很多约定,很多都涉及到带有定义和宏的预处理器。您最好的选择可能是查找并单独询问每个模式。您可能会在这里得到关于基本原理的深思熟虑的回答,以及良好的讨论。

是K&R的一个很好的后续行动。不要被标题所拖累。如果你了解C语言的基础知识,这本书是一本非常容易理解的书。它涵盖了K&R非常缺乏的许多真实世界的代码情况


尽管如此,阅读和编写代码确实是无可替代的。大多数现代约定并不是真正的标准,通常在不同的代码库中遵循不同的约定。它们只是解决每个人在用这种语言写作时所面临的问题和限制的常见方法。在我看来,最重要的是理解这些问题和限制是什么。

SQLITE\u API就是我所说的“调用类型习惯用法”的一个例子。它是一个预处理器指令,用于提高头文件的可移植性,头文件需要定义一些特定的调用模式,通常在主代码和DLL或类似文件之间

根据使用的平台和编译器,SQLITE_API通常会扩展到一些可用调用约定的组合,如


您应该在头文件中找到它的定义。

首先,您应该意识到定义“\u SQLITE3\u H\u3”实际上是被禁止的——所有以下划线开头,后跟另一个下划线或大写字母的名称都是保留的。当您这样做时,简单的答案是,最好避免在您定义的任何内容上使用前导下划线。把它们留给实现

就SQLLITE_API而言,它在不同平台上的定义可能有所不同。例如,如果在Windows上将其构建为DLL,则可能会定义如下:

#define SQLLITE_API __declspec(dllexport) __stdcall
#define SQLLITE_API __declspec(dllimport) __stdcall
另一方面,当您在代码中使用头时,它可能会扩展为以下内容:

#define SQLLITE_API __declspec(dllexport) __stdcall
#define SQLLITE_API __declspec(dllimport) __stdcall

这些基本上告诉编译器,当您构建DLL时,您希望导出函数(因此它对世界其他地方可见)。当您在自己的代码中使用它时,它会告诉编译器所讨论的函数将来自DLL。

Afaik GNU编码标准正在不断修订/更新,因此可能是“现代”风格的良好快照

Re:根据我的经验和我经常读到的资料,特别是单底或双底;人们普遍认为,避免使用双下划线前缀更安全,因为这些前缀通常是为特定于框架/系统/编译器和编译器相关的元素“保留”的,因此,仅用于定义它们的模块/包/单元/项目中的宏应该完全避免不加下划线前缀


大多数学院都有自己的语言编码标准和指导方针,这些标准和指导方针可能差异很大。一如既往,一致性是关键。

我推荐David R.Hanson的“C接口和实现:创建可重用软件的技术”。我认为这是一本关于C语言使用的最好的书。

阅读然后获得ISO C99标准并阅读。这些标准也被称为Ansi C,您还可以查找GNU编码标准或非常具体的linux内核编码风格。伯克利也有一些编码准则。所有这些都有利弊。另外还有更多的问题,他并不是在问包括警卫在内的人(一个教C必须知道的人的人)