Compilers will concatenate sections of the same name. You can use this trick to produce a concatenation of arrays across several files:
$ cat t1.c
__attribute__((section("some_array"))) int a[] = {1, 2, 3};
$ cat t2.c
__attribute__((section("some_array"))) int b[] = {4, 5, 6};
$ cat t.c
#include <stdio.h>
extern const int __start_some_array;
extern const int __stop_some_array;
int main() {
const int* ptr = &__start_some_array;
const int n = &__stop_some_array - ptr;
for (int i = 0; i < n; i++) {
printf("some_array[%d] = %d\n", i, ptr[i]);
}
return 0;
}
$ gcc -std=c99 -o t t.c t1.c t2.c && ./t
some_array[0] = 1
some_array[1] = 2
some_array[2] = 3
some_array[3] = 4
some_array[4] = 5
some_array[5] = 6
This is the mechanism that linkers use "under the hood" to get a list of C++ object initializers that need to run pre-main().It's unfortunate that there is no standard way of getting at this functionality in portable C, or to get it in C++ without actually running code pre-main(). Sometimes you really want a linker-initialized list things (of some sort) that have been linked in, without actually running code pre-main() (which has all kind of issues).
I would love to see a thing like this standardized in both C and C++. C++ compilers need it under the hood anyway.