问题
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