cc99clang-static-analyzer

What is the proper way of passing pointers to arrays in C?


Take this piece of code as an example:

#include <stdio.h>
void print_array(size_t size, unsigned (*myarray)[])
{
    printf("Array size: %lu\n", size);
    for (size_t i = 0; i < size; ++i)
            printf("%u ", (*myarray)[i]);
    printf("\n");
}
int main() {
    unsigned myarray[] = { 9, 8, 7, 6, 5 };
    print_array(sizeof(myarray) / sizeof(unsigned), &myarray);
    return 0;
}

When compiled with clang analyzer (via gcc 10.1.0) the warning is:

src/main.c:7:3: warning: 2nd function call argument is an uninitialized value
            printf("%u ", (*myarray)[i]);
            ^~~~~~~~~~~~~~~~~~~~~~~~~~~~

The output is:

Array size: 5
9 8 7 6 5 

What is the mistake in this piece of code and what is the proper way to pass pointers to arrays in C?


Solution

  • This seems like a false positive. There is no problem with the code - although the style is a bit exotic, it is all valid C.

    If the remark is about actual missing initialization, it could be related to the tool not checking the caller. But even if the analyser only takes the local translation unit in consideration, it can't go off and assume that passed variables are uninitialized by default. That would be a very strange assumption.

    Perhaps the analyser got spooked that you are actually passing a unsigned (*myarray)[5] to a function expecting a unsigned (*myarray)[] (pointer to incomplete type, an array of unspecified size). You could try to change the parameter to unsigned (*myarray)[size]) and see if it makes the tool happier.

    Edit: the array pointer types are compatible though, so the tool shouldn't complain for that reason either. As per C17 6.7.6.2/6, one or both of the array types can leave out the size specifier and still be compatible:

    For two array types to be compatible, both shall have compatible element types, and if both size specifiers are present, and are integer constant expressions, then both size specifiers shall have the same constant value.