Initializer lists can have trailing commas even in C89.
Trailing commas are allowed in enum bodies since C99.
Trailing commas are not allowed in function call argument lists (C23 6.5.3.1)
Storage-class specifiers should be at the beginning. (C23 6.11.5 ¶1)
In C99, signed integer division truncates towards zero. If the result was negative and rounded up, the remainder is negative. (C99 6.5.5)
Before C99, division of negative integers can round up or down (even when both operands are negative). The remainder can be positive or negative. (C89 3.3.5)
Unsigned integers consist of value bits and padding bits. Incorrect values for padding bits may produce a trap representation. When all value and padding bits are zero, this has to represent the integer zero (not a trap representation).
Every signed integer type has an unsigned counterpart, although other unsigned types such as _Bool do not have to have a signed counterpart. One bit in each unsigned type (either a value bit, or a padding bit) corresponds to the sign bit. Every valid signed representation where the sign bit is zero represents the same value in the unsigned type (C99 6.2.6.2 ¶5). A signed integer may use two’s complement representation, or before C23, sign-and-magnitude or one’s complement representation. Before C23, the representation for negative zero, or the most negative value in two’s complement, may be defined as a trap representation. Before C23, the sign bit may be in addition to the value bits of the unsigned counterpart, or the signed width may equal or be less than the unsigned width. In C23, the widths must be equal, and the most negative value is not a trap representation.
The unsigned char type cannot have padding bits, and an array of them can represent the bytes of any object. C11 signed char has the same width, therefore does not have any padding bits, but before C23 it may have a trap representation. Plain char is a distinct type, but otherwise has the same behaviour as either signed or unsigned char.
The uintN_t types do not have padding bits; therefore N must be a multiple of CHAR_BIT. The intN_t types use two’s complement representation, and cannot have padding bits nor a trap representation (C99 7.18.2.1).
Unsigned specified-width integers, even uint_fast64_t, may suffer promotion to signed int, with associated overflow. On the other hand, specifying a width signals the appropriate storage and machine instructions to be used. Also, (u)int_fast/least8_t have the advantage over (signed/unsigned) char of not being able to alias other types.
Posix requires 8-bit char, so (u)int8_t, and all (signed and unsigned) char expressions are converted to int rather than unsigned.
Pointers to different types are not necessarily compatible, except that a void pointer can hold a pointer to any type.
C doesn’t require that a void pointer be able to store a function pointer. Posix requires that function pointers returned from dlsym can be stored in its void pointer return type. Before the 2013 edition (TC1), it required all function pointers be convertible to void pointers (changed in bug 74).
Interpreted as pointers. The different meaning of array syntax between function parameters and other declarations is surprising. Dimension [static 1] implies the pointer cannot be null. Only allowed for complete element types (not void, nor FILE since C11 [6.2.5 ¶1, object type]).
Avoid when implementation independence is desired. The rules defined by C99 may not be intended, and do not match the behaviour of implementations. (https://stackoverflow.com/questions/77761618/formal-definition-of-restrict-fails-to-account-for-valid-cases)
The types in each of the following groups have the same size and alignment, and the same representation for values that they support, and may be interchanged in function arguments, return values, and unions.
Bitwise operations involving negative values depend on the signed integer representation, and can produce trap values. This includes negative operands, the bitwise complement of all signed values, and the bitwise complement of shorter unsigned values that are promoted to signed int. In general, it is better to use non-negative operands, and only bitwise-complement unsigned operands of at least unsigned int conversion rank.
A string conversion "%s" takes a pointer to a string of char. If no precision is specified, the string must include a null byte. If a precision is specified (e.g. "%.*s"), the C standard suggests the string may not need to be null terminated (C99 7.19.6.1 ¶8).