C code (violence)
- The shorter the code, the better. Code is read more often than is written.
- If you can avoid writing code, avoid it.
- Keep it as simple as possible, but not too much. Again, read vs write.
- Read the code. In case of a retch, take a few deep breaths. Continue.
- If there are no comments, it either means the code IS simple, or the code is impossible to understand unless you read a spec. See the top of a file to check if that’s the case.
- Do not put a copy of your license on top of every file. This is awkward.
/* */-style comments instead of C++ style. Use
//to comment out parts of code for a quick test.
- Put a link to a spec on top if the code implements it. For god’s sake, compiler can’t read and doesn’t care about your spec copy-pasted into the source code. If your code really needs a copy-pasted spec, it sucks.
- Prefer “magic” numbers with in-place comments (over a stupid enum somewhere) if your code deals with parsing of some complex format. It will be easier to debug such code while looking at the data it tries to parse.
- Try writing self-contained code. It should be easy to use and test it separately.
- Function name and ALL its arguments must start from a new line, ALWAYS just one
line. It should be possible to find its definition with
grep ^function *.c. Return type should be on the line before.
- Function prototype ALWAYS takes a SINGLE line, so
grep function *.houtputs the whole prototype. If it’s too long, you have a different problem.
- While it might look really stupid, prepend each function prototype in the header
externkeyword if it’s gonna be used in a new code, i.e. if it’s “public” in some way. It’s easy to see what global variables and functions the header is exporting then, by simply invoking
grep ^extern file.h. Private/internal function prototype can still be written without
extern, so that it won’t show up in the output.
- Function should return -1 in case of error, 0 in case of success. Not -2, or -3
unless you declare it in an
enumto handle specific errors differently (try to avoid this need).
- Do not expect functions to return -1 in case of error. Either use
- Always compare to
- Learn C operator precedence. Do not overuse parentheses.
- No manual inlining, compiler should do it.
#endifs, code should be self-contained. Consider a separate file with initialization function instead, or a platform-specific implementation, depending on the case.
#endifin headers. Include the headers once. See the one above.
enum, put it at the top of a file. It’s easy to both grep it and read it then. See
grep ^typedef file.h.
- No 80-column limit, although try to make it as short as easily readable.
- Initialize a variable near the place it’s gonna be used, not at its declaration.
- Do not use
memcpyunless you absolutely sure. Just use
- Never ever use
strcpy, even if you KNOW it fits.
- Never ever use
sprintf, even if you KNOW it fits.
- Never ever use
- Do not expect the stack to grow.
- Do not expect data to fit in a stack-allocated buffer. Use
- If you have defined
mainfunction and there is
setlocaleon the target OS, call
- Expect a crash on any unaligned access.
- Do not (over)use
valgrind. Use it more often.
- Before printing/logging a debug message consider its value. Only important information should be seen. Completely empty output is the best of all.
stderrover any kind of logging.
- Do not make assumptions.
- xkcd is always wrong.
Last update: June 06, 2021 08:58AM