@@ -464,6 +464,10 @@ ssize_t hex_write(FILE *stream, const void *buf, size_t len)
464464
465465Do not use old style K&R style C definitions.
466466
467+ Introduced in C99, `restrict` is a pointer qualifier that informs the compiler no other pointer will access the same object during its lifetime,
468+ enabling optimizations such as vectorization. Violating this assumption leads to undefined behavior.
469+ Use `restrict` judiciously.
470+
467471For function parameters, place one space after each comma, except at the end of a line.
468472
469473### Function-like Macros
@@ -477,10 +481,11 @@ When using function-like macros (parameterized macros), adhere to the following
477481
478482For example:
479483```c
480- #define SET_POINT(p, x, y) do { \
481- (p)->px = (x); \
482- (p)->py = (y); \
483- } while (0)
484+ #define SET_POINT(p, x, y) \
485+ do { \
486+ (p)->px = (x); \
487+ (p)->py = (y); \
488+ } while (0)
484489```
485490
486491While the extensive use of parentheses, as shown above, helps minimize some risks,
@@ -490,6 +495,45 @@ Other risks associated with macros include comparing signed and unsigned data or
490495Additionally, macros are not visible at runtime, making them impossible to step into with a debugger.
491496Therefore, use them with caution.
492497
498+ In general, macro names are typically written in all capitals, except in cases where readability is improved by using lowercase.
499+ For example:
500+ ```
501+ #define countof(a) (size)(sizeof(a) / sizeof(*(a)))
502+ #define lengthof(s) (countof(s) - 1)
503+ ```
504+
505+ Although all capitals are generally preferred for constants,
506+ lowercase can be used for function-like macros to improve readability.
507+ These function-like macros do not share the same namespace concerns as other macros.
508+
509+ For example, consider the implementation of a simple memory allocator.
510+ An arena can be represented by a memory buffer and an offset that begins at zero.
511+ To allocate an object, record the pointer at the current offset,
512+ advance the offset by the size of the object, and return the pointer.
513+ Additional considerations, such as alignment and checking for available space, are also required.
514+ ``` c
515+ #define new (a, n, t ) alloc(a, n, sizeof(t), _ Alignof(t))
516+
517+ typedef struct {
518+ char *begin, *end;
519+ } arena_t ;
520+
521+ void *alloc (arena_t * a, ptrdiff_t count, ptrdiff_t size, ptrdiff_t align)
522+ {
523+ ptrdiff_t pad = -(uintptr_t)a->begin & (align - 1);
524+ assert(count < (a->end - a->begin - pad) / size);
525+
526+ void *result = a->begin + pad;
527+ a->begin += pad + (count * size);
528+ return memset(result, 0, count * size);
529+ }
530+ ```
531+
532+ Using the `new` macro helps prevent several common errors in C programs.
533+ If types are mixed up, the compiler generates errors or warnings.
534+ Moreover, naming a macro `new()` does not conflict with variables or fields named `new`,
535+ because the macro form does not resemble a function call.
536+
493537### Use `const` and `static` effectively
494538
495539The `static` keyword should be used for any variables that do not need to be accessible outside the module where they are declared.
0 commit comments