I have a problem where i am linking multiple files in C. I want to define a constant representing array length at compile time, but save the user having to implement this in their file every time.
Here's the gist:
data.h - defines some constants
extern const int data[];
extern const int DATA_SIZE;
//other functions, not relevant
int get_second_item(void);
library_data.c - implements some of the functions in data.h
#include "data.h"
const int DATA_SIZE = sizeof(data) / sizeof(data[0]);
//can't compile because data is an incomplete type and hasn't been defined yet
int get_second_item(void)
{
return data[1];
}
public_data.c - user changes this with their data.
#include "data.h"
const int data[] = {1, 2, 3};
library_data.c and data.h are compiled first as .o files, amongst other library files that #include data.h and need to therefore use DATA_SIZE. Moving
const int DATA_SIZE = sizeof(data) / sizeof(data[0])
to public_data.c will of course work, but isn't a neat solution.
You can't use sizeof
on an extern
array of unspecified size (e.g. extern const int data[];
)
From http://c-faq.com/decl/extarraysize.html:
An extern array of unspecified size is an incomplete type; you cannot apply sizeof to it. sizeof operates at compile time, and there is no way for it to learn the size of an array which is defined in another file.
You have three options:
Declare a companion variable, containing the size of the array, defined and initialized (with sizeof) in the same source file where the array is defined:
file1.c: file2.c:
int array[] = {1, 2, 3}; extern int array[];
int arraysz = sizeof(array); extern int arraysz;
(See also question 6.23.)
#define a manifest constant for the size so that it can be used consistently in the definition and the extern declaration:
file1.h:
#define ARRAYSZ 3
extern int array[ARRAYSZ];
file1.c: file2.c:
#include "file1.h" #include "file1.h"
int array[ARRAYSZ];
Use some sentinel value (typically 0, -1, or NULL) in the array's last element, so that code can determine the end without an explicit size indication:
file1.c: file2.c:
int array[] = {1, 2, 3, -1}; extern int array[];