| > This pattern was officially standardized in C99, No it wasn't; the C99 flexible array uses [] not [1] or [0]. When using the [1] hack, you cannot use the sizeof the structure to get the offset, because it includes the [1] array. When using C99, you also cannot use sizeof to get the offset of the [0] element of the flexible array; sizeof is allowed to pretend that there is padding as if the flexible member were not there. > // The (N - 1) adjusts for the 1-element array in Payload struct
Payload *item = malloc(sizeof(Payload) + (N - 1) * sizeof(char))
>If you are in C++ you need a cast; the void * return value of malloc cannot implicitly convert to Payload *. Payload *item = static_cast<Payload *>(malloc(...));
Or of course a C cast if the code has to compile as C or C++: Payload *item = (Payload *) malloc(...);
Setting aside that issue for brevity, pretending we are in C, I would make the malloc expression: Payload *item = malloc(offsetof(Payload, elements) + N);
sizeof(char) is by definition 1, so we do not need to multiply N by it.By taking the offset of the elements array, we don't need to subtract 1 from N to account for the [1] element being skipped by sizeof. These kinds of little things take away complexity for something that must be carefully coded to avoid a memory safety issue. You really want the calculations around the memory to use the simplest possible formulas that are as easy as possible to reason about to convince yourself they are correct. Also, when you do use sizeof in a malloc expression, the following pattern avoids repeating the type name for the size, and also lets a pair of parentheses be dropped since sizeof only requires parentheses when the operand is a type: Payload *item = malloc(sizeof *item);
|