Repository navigation
Expand file tree
/
Copy pathindhill-cstyle.ms.tbl
More file actions
3349 lines (3340 loc) · 98.2 KB
/
Copy pathindhill-cstyle.ms.tbl
File metadata and controls
3349 lines (3340 loc) · 98.2 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
.\" ---------------- %snip --------------- % cut here -----------------
.\"
.\" Version of Indian Hill Style Manual (U of T amended)
.\" revision $Revision: 6.1 $
.\"
.\" make with ``... | tbl | {{di,}t,n}roff -ms ..''
.\" See the `.ds C C\"' macro, to set the C source code font.
.\"
.\" This document was really written with `troff' in mind. You will
.\" need to do significant hacking to get nice output with `nroff'.
.\"
.\" You may have comments, suggestions, bug fixes, etc. Send them to
.\" me and I will try to incorporate them (one way or another) in to
.\" a future version. If you change this document, please add a note
.\" that it has been modified and change the minor version number
.\" (e.g., version 5.0 becomes 5.1 or 5.0.zork, or whatever) and the
.\" last date of modification (printed in the footer of each page).
.\"
.\" pardo@cs.washington.edu or
.\" {rutgers,cornell,ucsd,ubc-cs,tektronix}!uw-beaver!june!pardo
.\"
.\"
.\"--------------------
.\" Footnote numbering
.ds f \\u\s-2\\n+f\\s+2\d
.nr f 0 1
.ds F \\n+F.
.nr F 0 1
.\"--------------------
.\" Select a font and a format for blocks of code.
.\" If your system has fixed-width fonts, then that's
.\" probably what you want to use. If your system doesn't
.\" support fixed-width fonts, then use the default.
.\" Really aggressive hackers will want to use vgrind (grind).
.\"
.ds C C\" \" Fixed-width font. (`.ds C CW' if no C?)
.\" `Ex': start example.
.de Ex
.DS \\$1
.ft \*C
.\" .DS \\$1 \" Use w/ any fixed-width font!
.\" .ft \*C \" Use fixed-width font.
.\" .ft R \" Default font if you don't have fixed-width.
.\" .vS \" Use vgrind. (BROKE?)
..
.\"
.\" `Ee': end example.
.de Ee
.DE
.\" .vE \" End vgrind block.
.\" .DE \" One of the fonts.
..
.\" Same idea, select a font for program text appearing `inline' in
.\" the text. use the same selection choices as for code blocks.
.\" Prepend `\&' in case the trailing arg starts w/ a period.
.\"
.\" Usage:
.\" .Ec foo (`foo' in code font)
.\" .Ec foo mp (`foomp', `foo' in code font, `mp' not)
.\" .Ec foo mp ka (`kafoomp', `foo' in code font, rest not)
.\"
.de Ep
.nh
\&\\$3\c
.ft \*C
\\$1\fP\\$2\" fixed-width font (not broke...)
.hy
.\"\&\\$3\f\*C\\$1\fP\\$2\" fixed-width font (BUG: BROKE!)
.\"\&\\$3\fC\\$1\fP\\$2\" fixed-width font
.\" \&\\$3\fB\\$1\fP\\$2\" default (general) font
..
.\" Same idea, select a font for `ideas' (concepts) that appear
.\" in the text.
.de Ec
\&\\$3\fI\\$1\fP\\$2
..
.\"--------------------
.\"
.nr x \w' '\" find width of 4 spaces.
.ta \nxu +\nxu +\nxu +\nxu +\nxu +\nxu +\nxu +\nxu +\nxu \" set tabs using that
.\"
.\"--------------------
.\" Long digressionary comment: There's lots of embedded junk that
.\" acts as ``rationale'' for rules or explains something or is of
.\" some interest, but of limited relevance. Those embedded comments
.\" might well be interesting to somebody, thus they should PERHAPS
.\" optionally be
.\"
.\" (a) ignored (yes!)
.\" (b) printed as endnotes
.\" (c) printed as footnotes
.\" (d) printed as inline text
.\"
.\" That is,
.\"
.\" mumble, foo, bar, zork.
.\" .BS
.\" The zoop machine bit-aligns the user
.\" The foop machine byte-aligns the user.
.\" The boop machine floats the user right out the door.
.\" .ES
.\" Other sterling words of wisdom.
.\"
.\" So suppose that register `r' and macro/string `ZZ' are unused,
.\" then reasonable macros include:
.\"
.\" .de BS
.\" .if \\nr==0 .de ZZ ES
.\" .if \\nr==1 .BE
.\" .if \\nr==2 .FS
.\" ..
.\" .de ES
.\" .if \\nr==1 .EE
.\" .if \\nr==2 .FE
.\" ..
.\"
.\" Then, if register r is 0, everything from the .BS to the .ES will
.\" become the definition of a macro ZZ, which are never read back;
.\" thus it is effectively (and fairly efficiently) thrown away.
.\"
.\" If register r is 1, .BS invokes .BE, and .ES invokes .EE --
.\" supposing .BE and .EE are names for macros for end-notes, though
.\" such thing might not exist in the -ms macros. IMHO, the various
.\" comments shouldn't be end-nodes. End-notes are for things like
.\" "op. cit. pp. 6-42", never for actual commentary on the text; it's
.\" just too much effort to read them.
.\"
.\" If register r is 2, .BS invokes .FS, and .ES invokes .FE; and
.\" if register r has any other value, .BE and .ES do nothing at all,
.\" so the material comes out inline. (The text should probably be
.\" blocked out with a `.QP' and a `\fBRemark:\fP or some such; see
.\" Knuth's "dangerous bend" paragraphs in The TeXBook.)
.\"
.\" Using a register with a 1-character name because it works nicely
.\" with troff's -r option. With the above macros, doing nothing
.\" makes the optional comments to disappear, -rr1 makes them in to
.\" end-notes, -rr2 for footnotes, and -rr3 for inline text.
.\"
.\" It probably isn't a good idea to do all that, though. People will
.\" just get confused about versions. Better to just include or
.\" exclude the notes.
.\"
.\"----------------
.RP
.TL
Recommended C Style and Coding Standards
.AU
L.W. Cannon
R.A. Elliott
L.W. Kirchhoff
J.H. Miller
J.M. Milner
R.W. Mitze
E.P. Schan
N.O. Whittington
.AI
Bell Labs
.AU
Henry Spencer
.AI
Zoology Computer Systems
University of Toronto
.AU
David Keppel
.AI
EECS, UC Berkeley
CS&E, University of Washington
.AU
Mark Brader
.AI
SoftQuad Incorporated
Toronto
.AB
This document is an updated version of the
\fIIndian Hill C Style and Coding Standards\fP
paper,
with modifications by the last three authors.
It describes a recommended coding standard for
C
programs.
The scope is coding style, not functional organization.
.AE
.\"--------------------
.\" Headers/footers must be in double quotes because most versions
.\" of .OF, .OH, ... are BROKE. (They work until you get 10 arguments
.\" and then silently truncate...
.\" revision $Revision: 6.1 $
.\"
.OF "'Recommended C Coding Standards'Revision: 6.0'25 June 1990'"
.EF "'Recommended C Coding Standards'Revision: 6.0'25 June 1990'"
.nr PO 1.25i
.ta 0.5i 1.0i 1.5i 2.0i 2.5i 3.0i
.\"--------------------
.NH
Introduction
.PP
This document
is a modified version of a document from
a committee formed at AT&T's Indian Hill labs to establish
a common set of coding standards and recommendations for the
Indian Hill community.
.\"
.\" old:
.\"
.\" The scope of this work is C coding style,
.\" rather than the functional organization of programs
.\" or general issues such as the use of \fIgoto\fPs.
.\"
The scope of this work is C coding style.
Good style should encourage consistent layout, improve
portability, and reduce errors.
.\"
.\" "It's simply a matter of style, and while there
.\" are many wrong styles, there really isn't any
.\" one right style." -- Ray Butterworth
.\"
This work does not cover functional organization, or general
issues such as the use of
.Ec goto s.
We\*f
.FS
.IP \*F
The opinions in this document
do not reflect the opinions of all authors.
This is still an evolving document.
Please send comments and suggestions to
pardo@cs.washington.edu or
{rutgers,cornell,ucsd,ubc-cs,tektronix}!uw-beaver!june!pardo
.FE
have tried to combine previous work [1,6,8] on C style into a uniform
set of standards that should be appropriate for any project using C,
although parts are biased towards particular systems.
Of necessity, these standards cannot cover all situations.
Experience and informed judgement count for much.
Programmers who encounter unusual situations should
consult either
experienced C programmers or code written by experienced C
programmers (preferably following these rules).
.PP
The standards in this document are not of themselves required, but
individual institutions or groups may adopt part or all of them
as a part of program acceptance.
It is therefore likely that others at your institution will code in
a similar style.
Ultimately, the goal of these standards is to
increase portability, reduce maintenance, and above all
improve clarity.
.PP
Many of the style choices here are somewhat arbitrary.
Mixed coding style is harder to maintain than bad coding style.
When changing existing code it is better to conform to the
style (indentation, spacing, commenting, naming conventions)
of the existing code than it is to blindly follow this document.
.QP
``\fITo be clear is professional; not to be clear
is unprofessional.\fP'' \(em Sir Ernest Gowers.
.NH
File Organization
.PP
A file consists of various sections that should be separated by
several blank lines.
Although there is no maximum length limit for source files,
files with more than about 1000 lines are cumbersome to deal with.
The editor may not have enough temp space to edit the file,
compilations will go more slowly,
etc.
Many rows of asterisks, for example,
present little information compared to the time it takes to scroll past,
and are discouraged.
Lines longer than 79 columns are not handled well by all terminals
and should be avoided if possible.
Excessively long lines which result from deep indenting are often
a symptom of poorly-organized code.
.NH 2
File Naming Conventions
.PP
File names are made up of a base name,
and an optional period and suffix.
The first character of the name should be a letter
and all characters (except the period)
should be lower-case letters and numbers.
The base name should be eight or fewer characters and the
suffix should be three or fewer characters
(four, if you include the period).
These rules apply to both program files and
default files used and produced by the program
(e.g., ``rogue.sav'').
.\"
.\" 8 + 1 + 3 + ",v" fits RCS into Version 7 filesystems.
.\" MS-DOS does 8 + "." + 3.
.\"
.PP
Some compilers and tools require certain suffix conventions for names
of files [5].
The following suffixes are required:
.IP \0\0\(bu
C source file names must end in \fI.c\fP
.IP \0\0\(bu
Assembler source file names must end in \fI.s\fP
.LP
The following conventions are universally followed:
.IP \0\0\(bu
Relocatable object file names end in \fI.o\fP
.IP \0\0\(bu
Include header file names end in \fI.h\fP.
.\"
.\" \*f.
.\" .FS
.\" .IP \*F
.\"
An alternate convention that may
be preferable in multi-language environments
is to suffix both the language type and \fI.h\fP
(e.g. ``foo.c.h'' or ``foo.ch'').
.\" .FE
.IP \0\0\(bu
Yacc source file names end in \fI.y\fP
.IP \0\0\(bu
Lex source file names end in \fI.l\fP
.PP
C++ has compiler-dependent suffix conventions,
including \fI.c\fP, \fI..c\fP, \fI.cc\fP, \fI.c.c\fP, and \fI.C\fP.
Since much C code is also C++ code, there is no clear solution here.
.PP
In addition,
it is conventional to use ``Makefile'' (not ``makefile'') for the
control file for \fImake\fP (for systems that support it)
and ``README'' for a summary of the contents
of the directory or directory tree.
.\"
.\" Having ``README'' in caps breaks the "monocase" rule, but is
.\" convention. Same for ``Makefile''.
.\"
.NH 2
Program Files
.PP
The suggested order of sections for a program file is as follows:
.IP 1.
First in the file is a prologue that tells what is in that file.
A description of the purpose of the objects in the files (whether
they be functions, external data declarations or definitions, or
something else) is more useful than a list of the object names.
The prologue may optionally contain author(s),
revision control information, references, etc.
.IP 2.
Any header file includes should be next.
If the include is for a non-obvious reason,
the reason should be commented.
In most cases, system include files like \fIstdio.h\fP should be
included before user include files.
.IP 3.
Any defines and typedefs that apply to the file as a whole are next.
One normal order is to have
``constant'' macros first,
then ``function'' macros, then typedefs and enums.
.IP 4.
Next come the global (external) data declarations,
usually in the order: externs, non-static globals, static globals.
If a set of defines applies to a particular piece of global data
(such as a flags word), the defines should be immediately after
the data declaration or embedded in structure declarations,
indented to put the defines one level
deeper than the first keyword of the declaration to which they apply.
.IP 5.
The functions come last,
and should be in some sort of meaningful order.
Like functions should appear together.
A ``breadth-first''
approach (functions on a similar level of abstraction together) is
preferred over depth-first (functions defined as soon as possible
before or after their calls).
Considerable judgement is called for here.
If defining large numbers of essentially-independent utility
functions, consider alphabetical order.
.NH 2
Header Files
.PP
Header files are files that are included in other files prior to
compilation by the C preprocessor.
Some, such as \fIstdio.h\fP, are defined at the system level
and must included by any program using the standard I/O library.
Header files are also used to contain data declarations and defines
that are needed by more than one program.
Header files should be functionally organized,
i.e., declarations for separate subsystems
should be in separate header files.
Also, if a set of declarations is likely to change when code is
ported from one machine to another, those declarations should be
in a separate header file.
.PP
Avoid private header filenames that are the same
as library header filenames.
The statement
.Ep #include
.Ep """math.h"""
.\"
.\" Or try .Ep math.h """" """"
.\"
will include the standard library math header file
if the intended one is not
found in the current directory.
If this is what you \fIwant\fP to happen,
comment this fact.
Don't use absolute pathnames for header files.
Use the
.Ec <name>
construction for getting them from a standard
place, or define them relative to the current directory.
The ``include-path'' option of the C compiler
(\-I on many systems)
is the best way to handle
extensive private libraries of header files; it permits reorganizing
the directory structure without having to alter source files.
.PP
Header files that declare functions or external variables should be
included in the file that defines the function or variable.
That way, the compiler can do type checking and the external
declaration will always agree with the definition.
.PP
Defining variables in a header file is often a poor idea.
Frequently it is a symptom of poor partitioning of code between files.
Also, some objects like typedefs and initialized data definitions
cannot be seen twice by the compiler in one compilation.
On some systems, repeating uninitialized declarations
without the \fIextern\fP keyword also causes problems.
Repeated declarations can happen if include files are nested
and will cause the compilation to fail.
.PP
Header files should not be nested.
.\"
.\" Many people disagree strongly with this.
.\" However, if you are to use \fIone\fP style, then this is best.
.\" The #ifndef/#define/.../#endif approach (below) often causes
.\" compilations to go much slower.
.\" A #endinput directive would be nice.
.\"
The prologue for a header file should, therefore, describe what
other headers need to be #included for the header to be functional.
In extreme cases, where a large number of header files are to be
included in several different source files,
it is acceptable to put all common #includes in one include file.
.PP
It is common to put the following into each
.Ec .h
file
to prevent accidental double-inclusion.
.Ex
#ifndef EXAMPLE_H
#define EXAMPLE_H
\&... \fI/* body of example.h file */\fP
#endif /* EXAMPLE_H */
.Ee
.LP
This double-inclusion mechanism should not be relied upon,
particularly to perform nested includes.
.NH 2
Other Files
.PP
It is conventional to have a file called ``README'' to document both
``the bigger picture'' and issues for the program as a whole.
For example, it is common to include a list of all conditional
compilation flags and what they mean.
It is also common to list files that are machine dependent, etc.
.NH
Comments
.QP
.ad r
``\fIWhen the code and the comments disagree,
both are probably wrong.\fP'' \(em Norm Schryer
.\" \fIBumper-Sticker Computer Science\fP,
.\" Jon Bently's \fIProgramming Pearls\fP column,
.\" Communications of the ACM (CACM),
.\" September 1985, Volume 28, Number 9.
.\"
.\" ``\fIMany's the time when I've thanked the Doug A. Gwyn of past
.\" years for anticipating future maintenance questions and providing
.\" helpful information in the original sources.\fP'' \(em Doug A.
.\" Gwyn
.\"
.br
.ad b
.PP
The comments should describe \fIwhat\fP is happening,
\fIhow\fP it is being done,
what parameters mean,
.\"
.\" BUG:
.\" By X3.159-1989, ``formal parameters'' are called `parameters' and
.\" ``actual parameters'' are called `arguments'. A somewhat relaxed
.\" form lets us call anything an argument, but only some formal
.\" parameters are `parameters'.
.\" The two usages are used inconsistantly in this document.
.\"
which globals are used and which are modified,
and any restrictions or bugs.
Avoid, however, comments that are clear from the code,
as such information rapidly gets out of date.
Comments that disagree with the code are of negative value.
Short comments should be
\fIwhat\fP comments, such as ``compute mean value'',
rather than \fIhow\fP comments such as
``sum of values divided by n''.
C is not assembler;
putting a comment at the top of a 3\-10 line section telling what it
does overall is often more useful than a comment on each line
describing micrologic.
.PP
Comments should justify offensive code.
The justification should be that something bad will happen if
unoffensive code is used.
Just making code faster is not enough to rationalize a hack;
the performance must be \fIshown\fP to be unacceptable
without the hack.
The comment should explain the unacceptable behavior and describe why
the hack is a ``good'' fix.
.PP
Comments that describe data structures, algorithms, etc., should be
in block comment form with the opening
.Ep /*
in columns 1-2, a
.Ep *
in column 2 before each line of comment text,
and the closing
.Ep */
in columns 2-3.
An alternative is to have
.Ep **
in columns 1-2, and put the closing
.Ep */
also in 1-2.
.Ex L
/*
* Here is a block comment.
* The comment text should be tabbed or spaced over uniformly.
* The opening slash-star and closing star-slash are alone on a line.
*/
.Ee
.Ex L
/*
** Alternate format for block comments
*/
.Ee
.PP
Note that \fIgrep '^.\e*'\fP will catch all block comments in the
file\*f.
.FS
.IP \*F
Some automated program-analysis
packages use different characters before comment lines as
a marker for lines with specific items of information.
In particular, a line with a
.Ep \- ' `
in a comment preceding a function
is sometimes assumed to be a one-line summary of the function's
purpose.
.FE
Very long block comments such as drawn-out discussions and copyright
notices often start with
.Ep /*
in columns 1-2, no leading
.Ep *
before lines of text, and the closing
.Ep */
in columns 1-2.
Block comments inside a function are appropriate, and
they should be tabbed over to the same tab setting as the code that
they describe.
One-line comments alone on a line should be indented to the tab
setting of the code that follows.
.Ex
if (argc > 1) {
/* Get input file from command line. */
if (freopen(argv[1], "r", stdin) =\^= NULL) {
perror (argv[1]);
}
}
.Ee
.PP
Very short comments may appear on the same line as the code they
describe,
and should be tabbed over to separate them from the statements.
If more than one short comment appears in a block of code
they should all be tabbed to the same tab setting.
.Ex
if (a =\^= EXCEPTION) {
b = TRUE; /* special case */
} else {
b = isprime(a); /* works only for odd a */
}
.Ee
.NH
Declarations
.PP
Global declarations should begin in column 1.
All external data declaration should be preceded by the
.Ec extern
keyword.
If an external variable is an array that is defined with an explicit
size, then the array bounds must be repeated in the extern
declaration unless the size is always encoded in the array
(e.g., a read-only character array that is always null-terminated).
Repeated size declarations are
particularly beneficial to someone picking up code written by another.
.\"
.\" /* foo.h */
.\" #define SIZE 1234
.\" extern int zork[SIZE]; /* ... and not `extern int zork[];' */
.\"
.\" /* foo.c */
.\" int zork[SIZE];
.\"
.PP
The ``pointer'' qualifier,
.Ep * ', `
should be with the variable name rather
than with the type.
.Ex
char *s, *t, *u;
.Ee
instead of
.Ex
char* s, t, u;
.Ee
which is wrong, since
.Ep t ' `
and
.Ep u ' `
do not get declared as pointers.
.PP
Unrelated declarations, even of the same type,
should be on separate lines.
A comment describing the role of the object being declared should be
included, with the exception
that a list of
.Ec #define d
constants do not need comments
if the constant names are sufficient documentation.
The names, values, and comments
are usually
.\" should be
tabbed so that they line up underneath each other.
Use the tab character rather than blanks (spaces).
For structure and union template declarations,
each element should be alone on a line
with a comment describing it.
The opening brace
.Ep { \^\^) (\^
should be on the same line as the structure
tag, and the closing brace
.Ep } \^) (\^\^
should be in column 1.
.Ex
struct boat {
int wllength; /* water line length in meters */
int type; /* see below */
long sailarea; /* sail area in square mm */
};
/* defines for boat.type */
#define KETCH (1)
#define YAWL (2)
#define SLOOP (3)
#define SQRIG (4)
#define MOTOR (5)
.Ee
.\"
.\" If this formatting `loses', you can probably fix it, but you'll
.\" have to be careful about tabs that appear later.
.\"
.\" .\" Set up a tab field, with the worst-case tabbing, more or less
.\" .ta \w'MOTOR 'u
.\" .\" #define KETCH<tab>1 (etc.)
.\"
.LP
These defines are sometimes put right after the declaration of
.Ep type ,
within the
.Ep struct
declaration, with enough tabs after the
.Ep # \^' `
to indent
.Ep define
one level more than the structure member declarations.
When the actual values are unimportant,
the
.Ec enum
facility is better\*f.
.FS
.IP \*F
.Ec enum s
might be better anyway.
.FE
.Ex
enum bt { KETCH=1, YAWL, SLOOP, SQRIG, MOTOR };
struct boat {
int wllength; /* water line length in meters */
enum bt type; /* what kind of boat */
long sailarea; /* sail area in square mm */
};
.Ee
.PP
Any variable whose initial value is important should be
\fIexplicitly\fP initialized, or at the very least should be commented
to indicate that C's default initialization to zero
is being relied upon.
The empty initializer,
.Ep {\^} '', ``
should never be used.
Structure
initializations should be fully parenthesized with braces.
.\"
.\" Consider the following:
.\"
.\" struct foo {int i, j};
.\" struct foo bar[] = {1, 2, 3, 4};
.\" struct foo kung[] = {{1, 2}, {3, 4}};
.\" struct foo oh[] = {};
.\"
.\" `bar' is accepted, but is visually ambiguous.
.\" `oh' is also accepted. Don't do it -- what does it mean?
.\"
.\" The following is NOT ambiguous and is good style.
.\"
.\" struct foo kung[] = {{1}, {3}};
.\"
Constants used to initialize longs should be explicitly long.
Use capital letters; for example two long
.Ep 2l '' ``
looks a lot like
.Ep 21 '', ``
the number twenty-one.
.Ex
int x = 1;
char *msg = "message";
struct boat winner[] = {
{ 40, YAWL, 6000000L },
{ 28, MOTOR, 0L },
{ 0 },
};
.Ee
.PP
In any file which is part of a larger whole rather than a self-contained
program, maximum use should be made of the
.Ec static
keyword to make functions and variables local to single files.
Variables in particular should be accessible from other files
only when there is a clear
need that cannot be filled in another way.
Such usage should be commented to make it clear that another file's
variables are being used; the comment should name the other file.
If your debugger hides static objects you need to see during
debugging,
declare them as
.Ep STATIC
and #define
.Ep STATIC
as needed.
.PP
The most important types should be highlighted by typedeffing
them, even if they are only integers,
as the unique name makes the program easier to read (as long as there
are only a \fIfew\fP things typedeffed to integers!).
Structures may be typedeffed when they are declared.
Give the struct and the typedef the same name.
.Ex
typedef struct splodge_t {
int sp_count;
char *sp_name, *sp_alias;
} splodge_t;
.Ee
.PP
The return type of functions should always be declared.
If function prototypes are available, use them.
One common mistake is to omit the
declaration of external math functions that return
.Ec double .
The compiler then assumes that
the return value is an integer and the bits are dutifully
converted into a (meaningless) floating point value.
.QP
.ce
``\fIC takes the point of view that the programmer is always right.\fP'' \(em Michael DeCorte
.NH
Function Declarations
.PP
Each function should be preceded by a block comment prologue
that gives a short description of what the function does
and (if not clear) how to use it.
Discussion of non-trivial design decisions and
side-effects is also appropriate.
Avoid duplicating information clear from the code.
.PP
The function return type should be alone on a line,
(optionally) indented one stop\*f.
.FS
.IP \*F
``Tabstops'' can be blanks (spaces) inserted by your editor in clumps
of 2, 4, or 8.
Use actual tabs where possible.
.FE
Do not default to
.Ec int ;
if the function does not return a value then it should be given
return type \fIvoid\fP\*f.
.FS
.IP \*F
.Ep "#define"
.Ep void
or
.Ep "#define"
.Ep void
.Ep int
for compilers without the
.Ec void
keyword.
.FE
If the value returned requires a long explanation,
it should be given in the prologue;
otherwise it can be on the same line as the return type, tabbed over.
The function name
(and the formal parameter list)
should be alone on a line, in column 1.
Destination (return value) parameters
should generally be first (on the left).
All formal parameter declarations,
local declarations and code within the function body
should be tabbed over one stop.
The opening brace of the function body should be alone on a line
beginning in column 1.
.PP
Each parameter should be declared (do not default to
.Ec int ).
In general the role of each variable in the function should be described.
This may either be done in the function comment or, if each declaration
is on its own line, in a comment on that line.
Loop counters called ``i'', string pointers called ``s'',
and integral types called ``c'' and used for characters
are typically excluded.
If a group of functions all have a like parameter or local variable,
it helps to call the repeated variable by the same name in all
functions.
(Conversely, avoid using the same name for different purposes in
related functions.)
Like parameters should also appear in the same place in the various
argument lists.
.PP
Comments for parameters and local variables should be
tabbed so that they line up underneath each other.
Local variable declarations should be separated
from the function's statements by a blank line.
.\"
.\" int zork; /* Last known zork. */
.\" struct price_tag inventory[MAX_STORES][MAX_STOCK]
.\" /* Corporate structure. */
.\" some_really_long_type_name *tree;
.\" /* root of the parse tree */
.\" char *s; /* variable name */
.\"
.\" If a variable has an extremely long definition, the comment
.\" should come \fIafter\fP the declaration. Multiline comments
.\" for variables should be moved to the header and referenced
.\" from the comment.
.\"
.\" * Note 1: The variable `zork' has two lives. It first ...
.\" */
.\"
.\" void *zork; /* See header note #1. */
.\"
.PP
Be careful when you use or declare functions
that take a variable number of arguments (``varargs'').
There is no truly portable way to do varargs in C.
Better to design an interface that uses a fixed number of arguments.
If you must have varargs,
use the library macros for declaring functions with
variant argument lists.
.PP
If the function uses any external variables (or functions)
that are not declared globally in the file,
these should have their
own declarations in the function body using the
.Ec extern
keyword.
.PP
Avoid local declarations that override declarations at higher levels.
In particular, local variables
should not be redeclared in nested blocks.
Although this is valid C, the potential confusion is
enough that
\fIlint\fP will complain about it when given the \-h option.
.NH
Whitespace
.QP
.ad r
\fIint i;main(){for(;i["]<i;++i){--i;}"];read('-'-'-',i+++"hell\\
.br
o, world!\\n",'/'/'/'));}read(j,i,p){write(j/p+p,i---j,i/i);}\fP
.br
\(em Dishonorable mention, Obfuscated C Code Contest, 1984.
.br
Author requested anonymity.
.br
.ad b
.PP
.\"Use whitespace generously, both vertically and horizontally.
Use vertical and horizontal whitespace generously.
Indentation and spacing should reflect the block structure of the code;
e.g.,
there should be at least 2 blank lines between the end of one function
and the comments for the next.
.PP
A long string of conditional operators should be split
onto separate lines.
.Ex
if (foo->next=\^=NULL && totalcount<needed && needed<=MAX_ALLOT
&& server_active(current_input)) { ...
.Ee
Might be better as
.Ex
if (foo->next =\^= NULL
&& totalcount < needed && needed <= MAX_ALLOT
&& server_active(current_input))
{
...
.Ee
Similarly, elaborate
.Ec for
loops should be split onto different lines.
.Ex
for (curr = *listp, trail = listp;
curr != NULL;
trail = &(curr->next), curr = curr->next )
{
\& ...
.Ee
Other complex expressions, particularly those using the ternary
.Ec ?\^:
operator,
are best split on to several lines, too.
.Ex
c = (a == b)
? d + f(a)
: f(b) - d;
.Ee
.\" .PP
.\" Finally, the closing brace of long functions and very long blocks
.\" should include an ``end function'' or ``end block'' comment:
.\" .DS
.\" \& } /* end for (each list element) */
.\" \& ...
.\" } /* end function_name() */
.Ee
Keywords that are followed by expressions in parentheses
should be separated from the left parenthesis by a blank.
(The
.Ec sizeof
operator is an exception.)
.\"
.\" Because `sizeof' is an OPERATOR.
.\"
Blanks should also appear after commas in argument lists to help
separate the arguments visually.
On the other hand, macro definitions with arguments must
not have a blank between the name and the left parenthesis,
otherwise the C preprocessor will not recognize the argument list.
.\"
.\" The C preprocessor requires the left parenthesis,
.\" to be immediately after the macro name or else the argument list
.\" will not be recognized.
.\"
.NH
Examples
.\"
.\" Perhaps this should be a complete file?
.\"
.PP
.Ex
/*
* Determine if the sky is blue by checking that it isn't night.
* CAVEAT: Only sometimes right. May return TRUE when the answer
* is FALSE. Consider clouds, eclipses, short days.
* NOTE: Uses `hour' from `hightime.c'. Returns `int' for
* compatibility with the old version.
*/
int /* true or false */
skyblue()
{
extern int hour; /* current hour of the day */
return (hour >= MORNING && hour <= EVENING);
}
.Ee
.Ex
/*
* Find the last element in the linked list
* pointed to by nodep and return a pointer to it.
* Return NULL if there is no last element.
*/
node_t *
tail(nodep)