Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Passing an array of 'typedef struct' to a function

Tags:

arrays

c

typedef

I have the following situation:

file A.c:

typedef struct element
{
    uint16_t value_raw;
    float value_scaled;
    char *desc;
} element;

element sv[REG_READ_COUNT];

file A.h:

typedef struct element element;

file B.c:

#include "A.h"
void dostuff (element sv[]) { } 

at compile time I get "error: array type has incomplete element type" for the function argument definition in B.c.

What's the right way to do this? How can I pass an array of type 'element' into a function?

like image 711
Erik Nyquist Avatar asked Jan 10 '23 19:01

Erik Nyquist


2 Answers

In B.c, element is an incomplete type (it is not defined in A.h, only in A.c). C disallows array declarators with incomplete element types (as you've discovered). Here's the relevant text from the C99 draft:

6.7.5.2 Array declarators

Constraints

  1. In addition to optional type qualifiers and the keyword static, the [ and ] may delimit an expression or *. If they delimit an expression (which specifies the size of an array), the expression shall have an integer type. If the expression is a constant expression, it shall have a value greater than zero. The element type shall not be an incomplete or function type. The optional type qualifiers and the keyword static shall appear only in a declaration of a function parameter with an array type, and then only in the outermost array type derivation.

Emphasis mine. This applies to all array declarators, no matter where they occur: in variable declarations, typedefs, function parameter lists, etc.

To fix your code, put the full struct definition in A.h. Or, if dostuff doesn't actually need to work with the elements (e.g. simply to pass the "array" to some other function), you could use void dostuff(element *sv).

like image 137
nneonneo Avatar answered Jan 20 '23 01:01

nneonneo


Minimal code to reproduce the error.

struct element;
void dostuff (struct element sv[]) { } 

Testing on clang and gcc using coliru: http://coliru.stacked-crooked.com/a/e5e314deef461290
Result: GCC and clang always complain about arguments of type array of incomplete type, and never about pointer to incomplete type.

Relevant standard-quotes:

6.7.6.3 Function declarators (including prototypes)

[...]
4 After adjustment, the parameters in a parameter type list in a function declarator that is part of a definition of that function shall not have incomplete type.
[...]
7 A declaration of a parameter as ‘‘array of type’’ shall be adjusted to ‘‘qualified pointer to type’’, where the type qualifiers (if any) are those specified within the [ and ] of the array type derivation. If the keyword static also appears within the [ and ] of the array type derivation, then for each call to the function, the value of the corresponding actual argument shall provide access to the first element of an array with at least as many elements as specified by the size expression.

Well, up to here it looks like array of incomplete type was perfectly fine for an argument type, even in a definition.

6.2.5 Types

[...]
20 Any number of derived types can be constructed from the object and function types, as follows:

  • An array type describes a contiguously allocated nonempty set of objects with a particular member object type, called the element type. The element type shall be complete whenever the array type is specified. Array types are characterized by their element type and by the number of elements in the array. An array type is said to be derived from its element type, and if its element type is T, the array type is sometimes called ‘‘array of T’’. The construction of an array type from an element type is called ‘‘array type derivation’’.

The above quote explicitly disallows using array-syntax with an incomplete type, for every case.

Conclusion: All those compilers seem to be right, even though that restriction seems unneeded.


Anyway, the proper course is not putting a forward-declaration for the type, but the declaration for the type itself into the header-file, unless it shall be an opaque type.

In that case, you will have to use pointer-syntax for the argument-type directly.

like image 37
Deduplicator Avatar answered Jan 20 '23 02:01

Deduplicator