Forcing an array size in a function parameter in C when passing an array

喜欢而已 提交于 2020-12-05 11:34:52

问题


Context

In C, I have a function which take an array as a parameter. This parameter is used as an output in this function. The output is always the same size. I would:

  • make the required size clear for anyone reading the code (it will already be in the function comments, though),
  • ideally the compilation to output a warning or an error so I can prevent problems at compile-time instead of run-time.

A potential solution

I found here: https://hamberg.no/erlend/posts/2013-02-18-static-array-indices.html something which look like a solution but I am not able to get a warning or an error during the compilation if I try to pass a smaller array than the required size.

Here is my complete program main.c:

void test_array(int arr[static 5]);

int main(void)
{
    int array[3] = {'\0'};

    test_array(array); // A warning/error should occur here at compilation-time
                       // telling me my array does not meet the required size.

    return 0;
}

void test_array(int arr[static 5])
{
    arr[2] = 0x7; // do anything...
}

Contrary to this blog, I use gcc (version 7.4.0) instead of clang with the following command:

gcc -std=c99 -Wall -o main.out main.c

In my code, we can see that the test_array() function needs a 5 elements array. I am passing a 3 elements one. I would expect a message from the compiler about this.

Question

In C, how to force a function parameter being an array to be of a given size? In case it is not, it should be noticeable at compilation-time.


回答1:


If you pass a pointer to the array instead of a pointer to its first element, you will get an incompatible pointer warning:

void foo(int (*bar)[42])
{}

int main(void)
{
    int a[40];
    foo(&a);  // warning: passing argument 1 of 'foo' from incompatible pointer type [-Werror=incompatible-pointer-types]
    // note: expected 'int (*)[42]' but argument is of type 'int (*)[40]'

    int b[45];
    foo(&b);  // warning: passing argument 1 of 'foo' from incompatible pointer type [-Werror=incompatible-pointer-types]
    // note: expected 'int (*)[42]' but argument is of type 'int (*)[45]'
}

Compile with -Werror to make it an error.

godbolt




回答2:


To test that the size of the array (not pointer) being passed is at least 5 elements, a Static_assert can be used, and the necessary _Static_assert can be inserted via a preprocessor macro.

After the declaration of the function, insert:

#define test_array(arr) \
    do \
    { \
        _Static_assert(sizeof (arr) / sizeof *(arr) >= 5, "Array is too small."); \
       test_array(arr); \
    } while (0)

(The do … while (0) is a classic way of defining a macro to act syntactically like a statement, so that it can be followed by a ; and flow as expected with if statements and such.)

Before the definition of the function, insert:

#undef test_array

(If any more uses of the function follow, another copy of the #define must be inserted. Alternatively, the function could be defined early in the source file and followed by a #define, eliminating any need for further #undef or #define directives.)

Generally, such code is unlikely to be useful, as programs often pass pointers to the first elements of the arrays (or to elements in the middle of arrays), and it is not possible to test how many elements are at the space a pointer is pointing to. So this is useful only in code where we require an array to be given as the argument. And that requirement is not enforced by this code.



来源:https://stackoverflow.com/questions/56176512/forcing-an-array-size-in-a-function-parameter-in-c-when-passing-an-array

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!