💾 Archived View for ftrv.se › 3 captured on 2021-12-03 at 12:44:48. Gemini links have been rewritten to link to archived content
View Raw
More Information
⬅️ Previous capture (2021-11-30)
-=-=-=-=-=-=-
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.
- Use `/* */`-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 *.h` outputs 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 with `extern` keyword 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 `enum` to handle specific errors differently (try to avoid this need).
- Do not expect functions to return -1 in case of error. Either use `== 0`, `!= 0` or `< 0`.
- Always compare to `nil`/`NULL` explicitly.
- Learn C operator precedence. Do not overuse parentheses.
- No manual inlining, compiler should do it.
- No `#ifdefs`/`#endifs`, code should be self-contained. Consider a separate file with initialization function instead, or a platform-specific implementation, depending on the case.
- No `#include` in headers.
- No `#ifdef`/`#endif` in headers. Include the headers once. See the one above.
- Separate `typedef` from actual `struct` and `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`.
- Use `enum` instead of `#define` if possible.
- 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 `memcpy` unless you absolutely sure. Just use `memmove`.
- Never ever use `strcpy`, even if you KNOW it fits.
- Never ever use `sprintf`, even if you KNOW it fits.
- Never ever use `alloca`.
- Do not expect the stack to grow.
- Do not expect data to fit in a stack-allocated buffer. Use `malloc`/`free` if unsure.
- If you have defined `main` function and there is `setlocale` on the target OS, call `setlocale(LC_ALL, "C")` there.
- Expect a crash on any unaligned access.
- Do not (over)use `const`.
- Learn `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.
- Prefer `stderr` over any kind of logging.
- Do not make assumptions.
- xkcd is always wrong.