0

I want to define an array of structs, the first element of which I want to be the offset of this element in the array. It has to be done at compile time. I can auto-generate as one option. I was wondering if there is a simpler way?

my_array[] = { {0, ...}, {1, ...}, ... }

I have some #ifdefs which remove some items from initialization. So I would like to ignore them if possible, and hence the offset re-adjusted.

Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
user210504
  • 1,749
  • 2
  • 17
  • 36
  • possible duplicate of [Does C++ support compile-time counters?](http://stackoverflow.com/questions/6166337/does-c-support-compile-time-counters) – Jack Aug 08 '15 at 00:14
  • i changed it to offset. this is c not c++ – user210504 Aug 08 '15 at 00:15
  • I actually refered to the "offset". As that can easily be calculated from the index, what is the useage of adding explicitly? – too honest for this site Aug 08 '15 at 00:17
  • 2
    `gcc` allows functions with `__attribute__((constructor))` as an extension. They are called before `main()`, allowing you to effectively initialize global objects arbitrarily. – EOF Aug 08 '15 at 00:30
  • 1
    @Olaf: I've seen that sort of number (offset) used when the structure ends up being treated as a linked list and you need to be able to map back to the array containing the elements of the linked list without knowing the start address of the array. It's an odd-ball edge-case type situation rather than main-line coding, but it can be helpful occasionally. (It can usually also be resolved in other ways too, but that, of itself, is not sufficient reason to want to avoid it.) As to the main question, I'm not convinced there's a better alternative than code generation or run-time fixup. – Jonathan Leffler Aug 08 '15 at 00:45
  • I observe that the C++ [possible duplicate question](http://stackoverflow.com/questions/6166337/does-c-support-compile-time-counters) referenced by [Jack](http://stackoverflow.com/users/121747/jack) in his [comment](http://stackoverflow.com/questions/31888292/initialize-a-global-integer-array-with-a-monotonic-sequence-at-compile-time#comment51694229_31888292) references [BOOST_PP_COUNTER](http://www.boost.org/doc/libs/1_46_0/libs/preprocessor/doc/ref/counter.html) which could be used to do the job — but you'd probably generate the necessary code, and you might as well do it more simply. – Jonathan Leffler Aug 08 '15 at 00:51
  • @JonathanLeffler: Thanks for the explanation. I actually used something myself, but with addresses, not offsets. Problem with offsets is that you still nedd to know the base-address of the array. Anyway. I agree with the rest. auto-generation is the way to go. If a personal opinion is allowed: I'd use Python. – too honest for this site Aug 08 '15 at 00:55
  • 1
    If using gcc, you might think of the [`__COUNTER__`](https://gcc.gnu.org/onlinedocs/cpp/Common-Predefined-Macros.html#Common-Predefined-Macros) macro and recursive `#include`s. But that will limit the number of elements dramatically. Generated code is likely the easier way. – too honest for this site Aug 08 '15 at 01:00

1 Answers1

1

The only "standard" solution (very dirty!) is by __LINE__ macro. Let's suppose your records is represented by this structure:

struct x { int v; };

1) define a macro that expands to one element initializer:

#define ELEM { __LINE__ - 1 }

2) Creqate a file (i.e. "elem.c") containing the list of element initializers, one for each line, expressed throug the ELEM macro:

File "elem.c":

ELEM,
ELEM,
ELEM,
...

3) define your array as follows:

struct x my_array[] = {
#include "elem.c"
};

Clearly, this is a very unhandy solution, so I recommend you to write a simple source code generator instead.

Giuseppe Guerrini
  • 4,274
  • 17
  • 32