File: c-styleguide.txt

package info (click to toggle)
nutcracker 0.4.1%2Bdfsg-1
  • links: PTS, VCS
  • area: main
  • in suites: bullseye, buster, stretch
  • size: 1,388 kB
  • ctags: 1,493
  • sloc: ansic: 14,328; python: 1,147; sh: 854; makefile: 105
file content (425 lines) | stat: -rw-r--r-- 15,550 bytes parent folder | download | duplicates (2)
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
- No literal tabs. Expand tabs to 4 spaces.
- Indentation is 4 spaces.
- No more than 3 levels of indentation, otherwise you should think about
  refactoring your code.
- Use one statement per line.
- Make sure that your editor does not leave space at the end of the line.
- snake_case for variable, function and file names.
- Use your own judgment when naming variables and functions. Be as Spartan
  as possible. Eg: Using name like this_variable_is_a_temporary_counter
  will usually be frowned upon.
- Don’t use local variables or parameters that shadow global identifiers.
  GCC’s ‘-Wshadow’ option can help you to detect this problem.

- Avoid using int, char, short, long. Instead use int8_t uint8_t, int16_t,
  uint16_t, int32_t, uint32_t, int64_t, uint64_t, which are available in
  <stdint.h>. However, when interfacing with system calls and libraries
  you cannot get away from using int and char.
- Use bool for boolean variables. You have to include <stdbool.h>
- Avoid using a bool as type for struct member names. Instead use unsigned
  1-bit bit field. Eg:
  struct foo {
      unsigned is_bar:1;
  };
- Always use size_t type when dealing with sizes of objects or memory ranges.
- Your code should be 64-bit and 32-bit friendly. Bear in mind problems
  of printing, comparisons, and structure alignment. You have to include
  <intyptes.h> to get generic format specifier macros for printing.

- 80 column line limit.
- If you have to wrap a long statement (> 80 column), put the operator at the
  end of the line and indent the next line at the same column as the arguments
  in the previous column. Eg:
    while (cnt < 20 && this_variable_name_is_too_long &&
           ep != NULL) {
        z = a + really + long + statement + that + needs + three + lines +
            gets + indented + on + the + same + column + as + the +
            previous + column
    }

    and:

    int a = function(param_a, param_b, param_c, param_d, param_e, param_f,
                     param_g, param_h, param_i, param_j, param_k, param_l);

- Always use braces for all conditional blocks (if, switch, for, while, do).
  This holds good even for single statement conditional blocks. Eg:
    if (cond) {
        stmt;
    }
- Placement of braces for non-function statement blocks - put opening brace
  last on the line and closing brace first. Eg:
    if (x is true) {
        we do y
    }
- Placement of brace for functions - put the opening brace at the beginning
  of the next line and closing brace first. This is useful because several
  tools look for opening brace in column one to find beginning of C
  functions. Eg:
int
function(int x)
{
    body of the function
}

- Closing brace is empty on a line of its own, except in cases where it is
  followed by a continuation of the same statement, i.e. a "while" in a
  do-statement or an "else" in an if-statement, like this:
    do {
        body of do-loop
    } while (condition);

    and,

    if (x == y) {
        ..
    } else if (x > y) {
        ...
    } else {
        ....
    }

- Column align switch keyword and the corresponding case/default keyword. Eg:
    switch (alphabet) {
    case 'a':
    case 'b':
        printf("I am a or b\n");
        break;

    default:
        break;
    }

- Forever loops are done with for, and not while. Eg:
    for (;;) {
        stmt;
    }

- Don't use a space after a function name.
- Do not needlessly surround the return expression with parentheses.
- Use space after keywords. Exceptions are sizeof, typeof, alignof and
  __attribute__, which look like functions.
- Do not add spaces around (inside) parenthesized expressions.
    s = sizeof( sizeof(*p)) ); /* bad example */
    s = sizeof(sizeof(*p));    /* good example */
- Casts should not be followed by space. Eg:
  int q = *(int *)&p
- There is no need to type cast when assigning a void pointer to a non-void
  pointer, or vice versa.
- Avoid using goto statements. However there are some exceptions to this rule
  when a single goto label within a function and one or more goto statements
  come in handy when a function exits from multiple locations and some common
  work such as cleanup has to be done. Eg:
int
fun(void)
{
    int result = 0;
    char *buffer;

    buffer = malloc(1024);
    if (buffer == NULL) {
        return -1;
    }

    if (condition1) {
        while (loop1) {
            ...
        }
        result = 1;
        goto out;
    }

    ...
out:
    free(buffer);
    return result;
}
- When declaring pointer data, use '*' adjacent to the data name and not
  adjacent to the type name. Eg:
    int
    function(int *p)
    {
        char *p;
        <body of the function>
    }
- Use one space around (on each side of) most binary and ternary operators,
  such as any of these:
    =  +  -  <  >  *  /  %  |  &  ^  <=  >=  ==  !=  ?  :
  but no space after unary operators:
    &  *  +  -  ~  !  sizeof typeof alignof  __attribute__  defined
  no space before the postfix increment & decrement unary operators:
    ++  --
  and no space around the '.' and "->" structure member operators.

- 0 and NULL; use 0 for integers, 0.0 for doubles, NULL for pointers, and
  '\0' for chars.
- Test pointers against NULL. E.g, use:
    if (p == NULL)

    not:

    !(p)

- Do not use ! for tests unless it is a boolean. E.g. use:
    if (*p == '\0')

    not:

    if (!*p)

- Don't use assignments inside if or while-conditions. E.g, use:

    struct foo *foo;
    foo = malloc(sizeof(*foo));
    if (foo == NULL) {
        return -1
    }

    not:

    struct foo *foo;
    if ((foo = malloc(sizeof(*foo))) == NULL) {
        return -1;
    }

- Don't ever use typedef for structure types. Typedefs are problematic
  because they do not properly hide their underlying type; for example you
  need to know if the typedef is the structure itself or a pointer to the
  structure. In addition they must be declared exactly once, whereas an
  incomplete structure type can be mentioned as many times as necessary.
  Typedefs are difficult to use in stand-alone header files: the header
  that defines the typedef must be included before the header that uses it,
  or by the header that uses it (which causes namespace pollution), or
  there must be a back-door mechanism for obtaining the typedef.
- The only exception for using a typedef is when you are defining a type
  for a function pointer or a type for an enum. Eg:

  typedef void (*foo_handler_t)(int, void *);

  or:

  typedef enum types {
      TYPE_1,
      TYPE_2
  } types_t;

- Use just one variable declaration per line when variables are part of a
  struct. This leaves you room for a small comment on each item, explaining
  its use. Declarations should also be aligned. Eg, use:

  struct foo {
    int      *foo_a;   /* comment for foo_a */
    int      foo_b;    /* comment for foo_b */
    unsigned foo_c:1;  /* comment for foo_c */
  };

  and not:

  struct foo {
    int *foo_a, foo_b;
    unsigned foo_c:1;
  };

- For variable declaration outside a struct, either collect all the
  declarations of the same type on a single line, or use one variable
  per line if the variables purpose needs to be commented. Eg:
  char *a, *b, c;

  or:

  char *a, *b;
  char c;       /* comments for c */

- Avoid magic numbers because no-one has a clue (including the author) of
  what it means after a month.

- Function definitions should start the name of the function in column
  one. This is useful because it makes searching for function definitions
  fairly trivial. Eg:
static char *
concat(char *s1, char *s2)
{
  body of the function
}

- Function and variables local to a file should be static.
- Separate two successive functions with one blank line.
- Include parameter names with their datypes in function declaration. Eg:
void function(int param);

- Functions should be short and sweet, and do just one thing. They should
  fit on one or two screenfuls of text (80 x 24 screen size), and do one
  thing and do that well.
  The maximum length of a function is inversely proportional to the
  complexity and indentation level of that function. So, if you have a
  conceptually simple function that is just one long (but simple)
  case-statement, where you have to do lots of small things for a lot of
  different cases, it's OK to have a longer function.
  Another measure of the function is the number of local variables. They
  shouldn't exceed 5-10, or you're doing something wrong. Re-think the
  function, and split it into smaller pieces. A human brain can
  generally easily keep track of about 7 different things, anything more
  and it gets confused. You know you're brilliant, but maybe you'd like
  to understand what you did 2 weeks from now.
- Use const for function parameters passed by reference, if the passed
  pointer has no side effect.

- C style comments only. Don't use // for single line comments. Instead
  use /* ... */ style.
- For multi-line comments use the following style
    /*
     * This is the preferred style for multi-line
     * comments in the Linux kernel source code.
     * Please use it consistently.
     *
     * Description:  A column of asterisks on the left side,
     * with beginning and ending almost-blank lines.
     */

- To comment out block of code spanning several lines use preprocessor
  directive "#ifdef 0 ... #endif"

- Please write a brief comment at the start of each source file, with the
  file name and a line or two about the overall purpose of the file.

- All major functions should have comments describing what they do at the
  head of the function. Avoid putting comments in the function body unless
  absolutely needed. If possible, add a comment on what sorts of arguments
  the function gets, and what the possible values of arguments mean and
  what they are used for and the significance of return value if there is
  one. It is not necessary to duplicate in words the meaning of the C
  argument declarations, if a C type is being used in its customary fashion.
  If there is anything nonstandard about its use (such as an argument of
  type char * which is really the address of the second character of a
  string, not the first), or any possible values that would not work the
  way one would expect (such as, that strings containing newlines are not
  guaranteed to work), be sure to say so. Eg:

/*
 * Try to acquire a physical address lock while a pmap is locked. If we
 * fail to trylock we unlock and lock the pmap directly and cache the
 * locked pa in *locked. The caller should then restart their loop in case
 * the virtual to physical mapping has changed.
 *
 * Returns 0 on success and -1 on failure.
 */
int
vm_page_pa_tryrelock(pmap_t pmap, vm_paddr_t pa, vm_paddr_t *locked)
{
    ...

- The comment on a function is much clearer if you use the argument names
  to speak about the argument values. The variable name itself should be
  lower case, but write it in upper case when you are speaking about the
  value rather than the variable itself. Thus, “the inode number NODE_NUM”
  rather than “an inode”.

- Every struct definition should have an accompanying comment that
  describes what it is for and how it should be used.

- Finally, while comments are absolutely important to keep the code readable,
  remember that the best code is self-documenting. Giving sensible names to
  types and variables is much better than using obscure names that you must
  then explain through comments.

- Recommend using UPPERCASE for macro names. However, sometimes using
  lowercase for macro names makes sense when macros masquerade as well-known
  function calls. Eg, it makes sense to write the wrapper for the
  standard free() function in lowercase to keep the readability
  consistent:

#define my_free(_p) do {    \
    free(_p);               \
    (_p) = NULL;            \
} while (0)

- Use enums when defining more than one related constants. All enumeration
  values are in UPPERCASE.
- Avoid macros as much as possible and use inline functions, enums and const
  variables wherever you can.
- For macros encapsulating compound statements, right justify the backslashes
  and enclose it in do { ... } while (0)
- For parameterized macros, all the parameters used in the macro body must
  be surrounded by parentheses. Eg:
  #define ADD_1(_x) ((_x) + 1)

- Use sizeof(varname) instead of sizeof(type) whenever possible. Eg:
  char *p;
  p = malloc(sizeof(*p));   /* good example */
  p = malloc(sizeof(char)); /* bad example */

- All variables should be declared at the beginning of a scope block {..}.
  It is even preferred to declare all variables at the beginning of the
  function so that all the local variable declarations is in one place and
  we can see the comprehensive list in one glance.
- Global structs should be declared at the top of the file in which they
  are used, or in separate header files if they are used in multiple
  source files.
- Declarations of external functions and functions to appear later in the
  source file should all go in one place near the beginning of the file,
  somewhere before the first function definition in the file or else
  should go in a header file.
- Use of extern should be considered as evil, if it is used in header files
  to reference global variables.
- Don’t put extern declarations inside functions.

- Usually every *.c file should have an associated *.h file. There are some
  exceptions to this rule, such as unit tests and small *.c files containing
  just the main() function.
- Every header file in the source code must have preprocessor conditional
  to prevent the header file from being scanned multiple times and avoiding
  mutual dependency cycles. Alternatively you can use #pragma once directive,
  as it avoids name clashes and increases the compile speed. Eg, for a
  header file named foo.h, the entire contents of the header file must be
  between the guard macros as follows:

#ifndef _FOO_H_
#define _FOO_H_
...
#endif /* _FOO_H_ */

Or,

#pragma once
#ifndef _FOO_H_
#define _FOO_H_
...
#endif /* _FOO_H_ */

- Don't use #include when a forward declaration would suffice.
- Functions defined in header files should be static inline.

- Don’t make the program ugly just to placate GCC when extra warnings options
  such as ‘-Wconversion’ or ‘-Wundef’ are used. These options can help in
  finding bugs, but they can also generate so many false alarms that that
  it hurts readability to silence them with unnecessary casts, wrappers, and
  other complications.

- Conditional compilation: when supporting configuration options already
  known when building your program we prefer using if (... ) over conditional
  compilation, as in the former case the compiler is able to perform more
  extensive checking of all possible code paths. Eg, use:

  if (HAS_FOO)
    ...
  else
    ...

instead of:

  #ifdef HAS_FOO
    ...
  #else
    ...
  #endif

  A modern compiler such as GCC will generate exactly the same code in both
  cases and of course, the former method assumes that HAS_FOO is defined as
  either 0 or 1.

- Finally, rules are rules. Sometimes they are sensible and sometimes not
  and regardless of your preference, we would like you to follow them.
  A project is easier to follow if all project contributors follow the style
  rules so that they can all read and understand everyone's code easily. But
  remember, like all good rules, they are exceptions where it makes sense not
  to be too rigid on the grounds of common sense and consistency!