Search code examples
clanguage-lawyerundefined-behavior

Accessing array items generically through pointer to array of chars?


If I'm writing a generic algorithm, am I allowed to alias an array of unknown type as a pointer to an array where each element is the size provided without invoking undefined behavior?

For example, is there UB in the following code?

typedef void (*action_t)(const void *item);
void do(void *array, size_t eltCount, size_t eltSize, action_t action)
{

    // Convenient typedef.
    typedef char element[eltSize];
    element *elts = array;
    element *end = elts + eltCount;

    for (; elts != end; elts++) {
        action(elts);
    }
}

I know I can do this:

char *elts = array;
char *end = elts + eltCount * eltSize;

for (; elts != end; elts += eltSize) {
    action(elts);
}

But the first bit of code seems more idiomatic to me since the compiler does the pointer arithmetic for me. The function above compiles without warnings using both gcc and clang (relevant compilation flags are -std=c99 -O3 -fstrict-aliasing -pedantic-errors -Wextra -Wall). I'm also wondering about strict aliasing, but as far as I can tell, it seems like I'm not breaking it here since objects are allowed to be used indirectly via char*.


Solution

  • In C, a typedef doesn't introduce a new type. It just names a construct. The name and its definition are interchangeable. (The same is not true for, say, struct, where there is no way to express the structure's definition other than by its name.)

    So, as long as you're only talking about some form of char * -- which as you know, is special because any data pointer can be converted to it -- then you're relying on defined behavior.