I want to share the value of sizeof(array)
between two .c modules. The array is initialized in file A, so compiler knows the size at compile time and then I want to use the size of this array in another B file.
Example:
In A.c file:
int arr[] = {1, 2, 3};
.
.
.
for (int i = 0; i < sizeof(arr); i++); // that works
In A.h file:
extern int arr[];
In B.c file:
#include "A.h"
.
.
.
for (int i = 0; i < sizeof(arr); i++); // here compiler doesn't know size of this arr
Is there a way to make this work? I know why this doesn't work but maybe there is a sneaky trick to workaround this.
Is there a way to make this work? I know why this doesn't work but maybe there is a sneaky trick to workaround this.
This unfortunately is not very sneaky, but it works...
In some.h
//declare as extern for project global scope
extern int arr[];
extern size_t gSizeArray;
Then in some.c
//define and initialize extern variables in 1 (and only one) .c file,
int arr[] = { 1,2,3 };
size_t gSizeArray = sizeof(arr)/sizeof(arr[0]);
In someother.c
that includes some.h
#include "some.h"
//you can now see the value of gSizeArray in this file
printf("%zu\n%d,%d,%d\n", gSizeArray, arr[0], arr[1], arr[2]);//should output
3
1,2,3
caveat
The value of using an extern in this fashion is that the value of that variable can change in one module, and that same value can be seen in any .c
file that includes some.h
corollary
The problem of using an extern in this fashion is that the value of that variable can change in one module, and that same value can be seen in any .c
file that includes some.h
.
(or in other words, be careful. Globals, in particular extern
globals can be helpful, but they can also be dangerous. Particularly for maintainers of the code who are not also the author of the code, who may not be aware a variable is of extern
scope, and use it unwittingly in inappropriate ways.
By the way, there is probably more than you'll ever want to know about using extern scope in this post.
Make the initializer a macro, share it through the header, and then you can use the compiler to recount the elements for the extern
declaration:
//header.h
#define ARR_INIT { 1, 2, 3}
extern int arr[sizeof((int[])ARR_INIT)/sizeof(int)];
//file.c
#include "header.h"
int arr[] = ARR_INIT;
( On gcc/clang/tinycc, you can also do:
//header.h
#define ARR_INIT (int[]){ 1, 2, 3}
extern int arr[sizeof(ARR_INIT)/sizeof(ARR_INIT[0])];
//file.c
#include "header.h"
int arr[] = ARR_INIT;
which is more typesafe but won't work with -Wpedantic
as standard C doesn't allow compound literals as initializers for objects with static storage duration.
)
You could also share the size through a regular global, but that has disadvantages as such a size would no longer be an integer constant expression and so it wouldn't be usable where those are required (array sizes, bitfield-widths, case labels, static initializers).
You can do it f.e. by declaring both, the size
object (which contains the amount of elements of arr
) and the array arr
, with the extern
storage-class specifier so that they have external linkage in the header A.h
. This header you include in both .c
source files.
The value of the size
object as well as the size of the array arr
(by its initializer list) is specified in A.c
but can be used in B.c
.
The A.h
file:
#include <stdio.h> // for size_t.
extern int arr[];
extern size_t size;
The A.c
file:
#include "A.h"
#include <stdio.h> // for size_t.
int arr[] = { 1, 2, 3 };
size_t size = sizeof (arr) / sizeof (arr[0]);
for ( size_t i = 0; i < size; i++ )
{
arr[i] = arr[i] - 1;
}
The B.c
file:
#include "A.h"
#include <stdio.h>
for ( size_t i = 0; i < size; i++ )
{
printf("%d\n", arr[i]);
}
Output:
0
1
2
Side Note:
sizeof(arr)
does not yield the amount of elements in arr
; It yields the amount of bytes allocated for the whole array arr
. Since arr
is an array of type int
and not f.e. char
, where the amounts of elements is equal to the amount of allocated byte, this result is different to the amount of elements.
To gain the amount of elements use sizeof(arr) / sizeof(arr[0])
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With