📄 c-style.htm
字号:
<html>
<head>
<title>Aladdin's C coding guidelines</title>
<!-- $Id: C-style.htm $ -->
<!-- Originally: c-style.txt -->
</head>
<body>
<!-- [1.0 begin visible header] -------------------------------------------- -->
<!-- [1.1 begin headline] -------------------------------------------------- -->
<p><table width="100%" border="0">
<tr><th align="center" bgcolor="#CCCC00"><font size=6>
Aladdin's C coding guidelines
</font>
</table>
<!-- [1.1 end headline] ---------------------------------------------------- -->
<!-- [1.2 begin table of contents] ----------------------------------------- -->
<h2>Table of contents</h2>
<blockquote><ul>
<li><a href="#Summary">Summary of the coding guidelines</a>
<ul>
<li><a href="#Summary_preprocessor">Preprocessor</a>
<li><a href="#Summary_types">Types and scopes</a>
<li><a href="#Summary_formatting">Formatting</a>
<li><a href="#Summary_miscellany">Miscellany</a>
</ul>
<li><a href="#Introduction">Introduction</a>
<li><a href="#C_features">Use of C language features</a>
<ul>
<li><a href="#Preprocessor">Preprocessor</a>
<ul>
<li><a href="#Conditionals">Conditionals</a>
<li><a href="#Macros">Macros</a>
</ul>
<li><a href="#Types_declarations">Types and declarations</a>
<ul>
<li><a href="#Pointers_structures">Pointers and structures</a>
<li><a href="#Scalars">Scalars</a>
</ul>
<li><a href="#Scoping">Scoping</a>
<li><a href="#Other">Miscellany</a>
</ul>
<li><a href="#File_structuring">File structuring</a>
<ul>
<li><a href="#All_files">All files</a>
<li><a href="#Makefiles">Makefiles</a>
<li><a href="#C_code_generally">C code in general</a>
<ul>
<li><a href="#Headers">Headers (<b><tt>.h</tt></b> files)</a>
<li><a href="#Executable_code">Executable code (<b><tt>.c</tt></b> files)</a>
</ul>
</ul>
<li><a href="#Formatting">Formatting</a>
<ul>
<li><a href="#Indentation">Indentation</a>
<li><a href="#Spaces">Spaces</a>
<li><a href="#Parentheses">Parentheses</a>
</ul>
<li><a href="#Naming">Naming</a>
<ul>
<li><a href="#General_naming">General rules</a>
<li><a href="#Conventional_names">Names used by convention</a>
<ul>
<li><a href="#code"><b><tt>code</tt></b></a>
<li><a href="#status"><b><tt>status</tt></b></a>
</ul>
</ul>
<li><a href="#Miscellany">Miscellany</a>
<ul>
<li><a href="#Single_use_procedures">Single-use procedures</a>
<li><a href="#Local_variables">Local variables</a>
<li><a href="#Error_handling">Error-handling</a>
</ul>
</ul></blockquote>
<!-- [1.2 end table of contents] ------------------------------------------- -->
<!-- [1.3 begin hint] ------------------------------------------------------ -->
<p>
For other information, see the <a href="Readme.htm">Ghostscript
overview</a>.
<!-- [1.3 end hint] -------------------------------------------------------- -->
<hr>
<!-- [1.0 end visible header] ---------------------------------------------- -->
<!-- [2.0 begin contents] -------------------------------------------------- -->
<h1><a name="Summary"></a>Summary of the coding guidelines</h1>
<h2><a name="Summary_preprocessor"></a>Preprocessor</h2>
<ul>
<li>Use preprocessor conditionals that test for individual platforms or
compilers, if necessary, only in header files named xxx<b><tt>_.h</tt></b>.
<li>Don't define a macro if you can do it with a procedure.
<li>Use
<blockquote><b><tt>
gx_device_fubar * const fdev = (gx_device_fubar *)dev;
</tt></b></blockquote>
<p>
rather than
<blockquote><b><tt>
#define fdev ((gx_device_fubar *)dev)
</tt></b></blockquote>
<li>Put <b><tt>()</tt></b> around the body of expression-macro definitions,
and around each use of an argument.
<li>Make all variables referenced in a macro body arguments of the macro.
</ul>
<h2><a name="Summary_types"></a>Types and scopes</h2>
<ul>
<li>Use <b><tt>const</tt></b> for pointer referents (that is,
<b><tt>const T *</tt></b>) wherever possible.
<li>Use unions or (less preferably) casts in preference to
<b><tt>void *</tt></b>.
<li>Don't use anonymous structures or unions.
<li>Don't declare procedure parameters of type <b><tt>float</tt></b>,
<b><tt>short</tt></b>, or <b><tt>char</tt></b>.
<li>Never explicitly cast float to double.
<li>Use "<b><tt>private</tt></b>" instead of "<b><tt>static</tt></b>" at
the top level of a file.
<li>Don't create any new non-const static variables.
<li>Put externs in <b><tt>.h</tt></b> files, not <b><tt>.c</tt></b> files.
</ul>
<h2><a name="Summary_formatting"></a>Formatting</h2>
<ul>
<li><b><tt>gsindent</tt></b> (GNU <b><tt>indent</tt></b> + fixup script)
will do 98% of the job for you.
<li>Put indentation points every 4 spaces, with 8 spaces = 1 tab stop.
<li>"<b><tt>{</tt></b>" should always be the last non-blank character on
its line (except for comments); "<b><tt>}</tt></b>" should always be the
first non-blank on its line.
<li>Use spaces after comma ("<b><tt>,</tt></b>") and semicolon
("<b><tt>;</tt></b>"), around binary operators, and on both sides of the
parentheses for <b><tt>if</tt></b>, <b><tt>for</tt></b>, and
<b><tt>while</tt></b>, and nowhere else.
<li>Use parentheses only when mixing <b><tt>&&</tt></b> and
<b><tt>||</tt></b>, when mixing <b><tt>&</tt></b>, <b><tt>|</tt></b>
and shifts with each other or other operators, and around
"<b><tt>? :</tt></b>" expressions.
</ul>
<h2><a name="Summary_miscellany"></a>Miscellany</h2>
<ul>
<li>Use <b><tt>#include</tt></b> statements in the order
<ol>
<li><b><tt>*_.h</tt></b>
<li><b><tt>gs*.h</tt></b>
<li><b><tt>gx*.h</tt></b>
<li><b><tt>s*.h</tt></b>
<li><b><tt>i*.h</tt></b>
</ol>
<li>In names use full words rather than contractions, and don't run words
together.
<li>Don't assign new values to procedure parameters.
<li>Initialize local variables when they are declared.
</ul>
<hr>
<h1><a name="Introduction"></a>Introduction</h1>
<p>
The many rules that Ghostscript's code follows almost everywhere are meant
to produce code that is easy to read. It's important to observe them as
much as possible in order to maintain a consistent style, but if you find a
rule getting in your way or producing ugly-looking results once in a while,
it's OK to break it.
<hr>
<h1><a name="C_features"></a>Use of C language features</h1>
<h2><a name="Preprocessor"></a>Preprocessor</h2>
<h3><a name="Conditionals"></a>Conditionals</h3>
<p>
Using preprocessor conditionals can easily lead to unreadable code, since
the eye really wants to read linearly rather than having to parse the
conditionals just to figure out what code is relevant. It's OK to use
conditionals that have small scope and that don't change the structure or
logic of the program (typically, they select between different sets of
values depending on some configuration parameter), but where possible, break
up source modules rather than use conditionals that affect the structure or
logic.
<p>
In <b><tt>.c</tt></b> files don't use preprocessor conditionals that test
for individual platforms or compilers. Use them only in header files named
xxx<b><tt>_.h</tt></b>.
<h3><a name="Macros"></a>Macros</h3>
<p>
Ghostscript code uses macros heavily to effectively extend the rather
weak abstraction capabilities of the C language, specifically in the area of
memory management and garbage collection: in order to read Ghostscript code
effectively, you simply have to learn some of these macros as though they
were part of the language. The current code also uses macros heavily for
other purposes, but we are trying to phase these out as rapidly as possible,
because they make the code harder to read and debug, and to use the
rules that follow consistently in new code.
<p>
Define macros in the smallest scope you can manage (procedure, file, or
<b><tt>.h</tt></b> file), and <b><tt>#undef</tt></b> them at the end of
that scope: that way, someone reading the code can see the definitions
easily when reading the uses. If that isn't appropriate, define them in as
large a scope as possible, so that they effectively become part of the
language. This places an additional burden on the reader, but it can be
amortized over reading larger amounts of code.
<p>
Try hard to use procedures instead of macros. Use "<b><tt>inline</tt></b>"
if you really think the extra speed is needed, but only within a
<b><tt>.c</tt></b> file: don't put inline procedures in <b><tt>.h</tt></b>
files, because most compilers don't honor "<b><tt>inline</tt></b>" and
you'll wind up with a copy of the procedure in every <b><tt>.c</tt></b>
file that includes the <b><tt>.h</tt></b> file.
<p>
Don't use macros to define shorthands for casted pointers. For instance,
avoid
<blockquote><b><tt>
#define fdev ((gx_device_fubar *)dev)
</tt></b></blockquote>
<p>
and instead use
<blockquote><b><tt>
gx_device_fubar * const fdev = (gx_device_fubar *)dev;
</tt></b></blockquote>
<p>
The use of <b><tt>const</tt></b> alerts the reader that this is effectively
a synonym.
<p>
If you define a macro that looks like a procedure, make sure it will work
wherever a procedure will work. In particular, put parentheses around every
use of an argument within the macro body, so that the macro will parse
correctly if some of the arguments are expressions, and put parentheses
around the entire macro body. (This is still subject to the problem that an
argument may be evaluated more than once, but there is no way around this in
C, since C doesn't provide for local variables within expressions.)
<p>
If a macro generates anything larger than a single expression (that is, one
or more statements), surround it with <b><tt>BEGIN</tt></b> and
<b><tt>END</tt></b>. These work around the fact that simple statements and
compound statements in C can't be substituted for each other syntactically.
<p>
If you define macros for special loop control structures, make their uses
look somewhat like ordinary loops, for instance:
<blockquote>
<b><tt>BEGIN_RECT(xx, yy) {</tt></b><br>
... body indented one position ...<br>
<b><tt>} END_RECT(xx, yy);</tt></b>
</blockquote>
<p>
If at all possible, don't use free variables in macros -- that is, variables
that aren't apparent as arguments of the macro. If you must use free
variables, list them all in a comment at the point where the macro is
defined.
<p>
Preferably <b>CAPITALIZE</b> macro names.
<h2><a name="Types_declarations"></a>Types and declarations</h2>
<h3><a name="Pointers_structures"></a>Pointers and structures</h3>
<p>
Use <b><tt>const</tt></b> for pointer referents (that is,
<b><tt>const T *</tt></b>) wherever possible and appropriate.
Don't bother using it for anything else, except as described above for
casted pointers.
<p>
If you find yourself wanting to use <b><tt>void *</tt></b>, try to
find an alternative using unions or (in the case of super- and subclasses)
casts, unless you're writing something like a memory manager that really
treats memory as opaque.
<p>
Don't use anonymous structures if you can possibly avoid it, except perhaps
as components of other structures. Ideally, use the
"<b><tt>struct</tt></b>" keyword only for declaring named structure types,
like this:
<blockquote>
<b><tt>typedef struct xxx_yyy_s {</tt></b><br>
... members ...<br>
<b><tt>} xxx_yyy_t;</tt></b>
</blockquote>
<p>
Many older structure names don't have <b><tt>_t</tt></b> on the end, but it
should be used in all new code. (The <b><tt>_s</tt></b> name is needed
only to satisfy some debuggers. No code should use it.)
<p>
If a procedure parameter is itself a procedure, do list its
parameter types rather than just using <b><tt>()</tt></b>. For example,
<blockquote><b><tt>
int foo(P1(int (*callback)(P2(int, int))));
</tt></b></blockquote>
<p>
rather than just
<blockquote><b><tt>
int foo(P1(int (*callback)()));
</tt></b></blockquote>
<h3><a name="Scalars"></a>Scalars</h3>
<p>
Don't declare parameters as being of type <b><tt>float</tt></b>,
<b><tt>short</tt></b>, or <b><tt>char</tt></b>. If you do this and forget
to include the prototype at a call site, ANSI compilers will generate
incompatible calling sequences. Use <b><tt>floatp</tt></b> (a synonym for
<b><tt>double</tt></b>, mnemonic for "float parameter") instead of
<b><tt>float</tt></b>, and use <b><tt>int</tt></b> or <b><tt>uint</tt></b>
instead of <b><tt>short</tt></b> or <b><tt>char</tt></b>.
<p>
ANSI compilers in their default mode do all floating point computations in
double precision, so never cast a float to a double explicitly.
<p>
Unless there's a good reason for doing otherwise, return
<b><tt>floatp</tt></b> (<b><tt>double</tt></b>) rather than
<b><tt>float</tt></b> values. Many floating point units do everything in
double internally and have to do extra work to convert between double and
float.
<h2><a name="Scoping"></a>Scoping</h2>
<p>
Use "<b><tt>private</tt></b>" instead of "<b><tt>static</tt></b>" for
constructs (procedures and variables) declared at the outermost scope of a
file. This allows making such constructs either visible or invisible to
profilers with a single changed <b><tt>#define</tt></b>.
<p>
Don't create any new non-<b><tt>const</tt></b> static variables (whether
exported or local to a file): they are incompatible with reentrancy, and
we're in the process of eliminating all of them.
<p>
Avoid <b><tt>static const</tt></b> data, but don't knock yourself out over
it, especially if it's local to a file.
<p>
Avoid <b><tt>extern</tt></b> in <b><tt>.c</tt></b> files: put it in header
files.
<h2><a name="Other"></a>Miscellany</h2>
<p>
The most important descriptive comments are ones in header files that
describe structures, including invariants; but every procedure or structure
declaration, or group of other declarations, should have a comment. Don't
spend a lot of time commenting executable code unless something unusual or
subtle is going on.
<p>
In older code, calling a variable or parameter procedure always used
explicit indirection, for instance, <b><tt>(*ptr->func)(...)</tt></b>
rather than <b><tt>ptr->func(...)</tt></b>. Since all current compilers
accept the latter form, use it in new code.
<hr>
<h1><a name="File_structuring"></a>File structuring</h1>
<h2><a name="All_files"></a>All files</h2>
<p>
Every code file should start with comments containing
<ol>
<li>a copyright notice,
<li>the name of the file in the form of an RCS Id:
<blockquote><b><tt>
/*Id$: filename.c $*/
</tt></b></blockquote>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -