C: How to determine sizeof(array) / sizeof(struct)

2019-06-15 18:35发布

问题:

Defines the type x and an array X of that type.

x.h:

typedef struct _x {int p, q, r;} x;
extern x X[];

Separate file to keep the huge honking array X.

x.c:

#include "x.h"
x X[] = {/* lotsa stuff */};

Now I want to use X:

main.c:

#include "x.h"

int main()
{
    int i;

    for (i = 0; i < sizeof(X)/sizeof(x); i++) /* error here */
        invert(X[i]);

    return 0;
}

main.c won't compile; the error is:

error: invalid application of ‘sizeof’ to incomplete type ‘struct x[]’

How do I get the size of X without hardcoding it?

回答1:

In x.h add:

extern size_t x_count;

In x.c add:

size_t x_count = sizeof(X)/sizeof(x);

Then use the variable x_count in your loop.

The division has to be done in the compilation unit that contains the array initializer, so it knows the size of the whole array.



回答2:

If it is possible to place a termination indicator at the end of the array, such as:

x X[] = {/* lotsa stuff */, NULL};

It might be that the number of elements in the array would be irrelevant:

#include "x.h"

int main()
   {
   x *ptr = X;

   while(ptr)
      invert(ptr++);

   return 0;
   }

If the number of elements in the array is needed, the above method can be also be used to count the elements.



回答3:

Here a solution using compound literals:

in .h

typedef struct _x {int p, q, r} x;

#define LOTSA_STUFF        {1, 2, 3}, {4, 5, 7}
#define LOTSA_STUFF_SIZE  sizeof ((x[]) {LOTSA_STUFF})

extern x X[LOTSA_STUFF_SIZE];

and in .c

x X[LOTSA_STUFF_SIZE] = {LOTSA_STUFF};

For the definition in .c, you can even do better and use a static assert (definition of the STATIC_ASSERT is let as an exercise for the reader ;):

x X[] = {LOTSA_STUFF};

STATIC_ASSERT(sizeof X != LOTSA_STUFF_SIZE, "oops, sizes are not equal");


回答4:

If you simply include x.h, the compiler has no idea what the real size of X is. Just by looking at x.h, there is no way to guess. You have to declare X with a size:

extern x X[15];


回答5:

You can't do that. But you can provide a way to get the size.

In addition to

extern x X[];

Add

extern size_t xArraySize;

or, preferably,

extern size_t xArraySize(void);

in x.h

Define it in x.c.

Change your loop to:

for (i = 0; i < xArraySize(); i++)
    invert(X[i]);