-2

I am having trouble putting together some code in which I wish to have the following:

  • Have a header file myHeader.h in which I create a type struct myStruct with members int number1, int number2 and int number3. This file would also contain a "getter" prototype for getting the address of each of the members in a struct instance.

  • A translation unit (file.c) in which I declare a static instance of struct myStruct, i.e. static struct myStruct myStructInstance. This translation unit defines the "getter" functions (I will illustrate with a code example at the end of the post).

  • Another header file anotherHeader.h in which I wish to - now this is a tricky bit that's causing problems for me - get the addresses of each of the members of a static structure and use them for something.

Here's an example to show what I am talking about.

myHeader.h

struct myStruct{
    int number1;
    int number2;
    int number3;
};

int* get_number1(void);
int* get_number2(void);
int* get_number3(void);

file.c

#include <myHeader.h>

static struct myStruct myStructInstance = {
        .number1 = 0,
        .number2 = 0,
        .number3 = 0
};

int* get_number1(void){
    struct myStruct* ptr_myStructInstance = &(myStructInstance);
    int* number1Address = &(ptr_myStructInstance->number1);
    return number1Address;
}

int* get_number2(void){
    struct myStruct* ptr_myStructInstance = &(myStructInstance);
    int* number2Address = &(ptr_pfcVariables->number2);
    return number2Address;
}

int* get_number3(void){
    struct myStruct* ptr_myStructInstance = &(myStructInstance);
    int* number3Address = &(ptr_myStructInstance->number3);
    return number3Address;
}

anotherHeader.h

#include <myHeader.h>

int* pNumber1 = get_number1();

int* pNumber2 = get_number2();

int* pNumber3 = get_number3();

The problem is that the code shown above throws "initializer element is not constant" error in anotherHeader.h. I've read a few answers as to why we cannot use non-constant expressions when initializing variables with static storage duration, however I do not understand how this relates to my code.

avg
  • 223
  • 3
  • 11
  • 2
    Why not simply do e.g. `return &myStructInstance.number1`? – Some programmer dude Aug 18 '16 at 23:20
  • As for your `anotherHeader.h`, why do you *define* the variables in the header? That means the header file can't be included in multiple source files. – Some programmer dude Aug 18 '16 at 23:22
  • @JoachimPileborg No particular reason - in fact, that's what I had originally. It wasn't working either way, and I just pasted whatever code there is right now. – avg Aug 18 '16 at 23:22
  • @JoachimPileborg And yes, you are absolutely correct about defining the variables in the header - thank you for pointing this our for me! – avg Aug 18 '16 at 23:25
  • It would be interesting to know what you're actually trying to accomplish. Everything about this has a bad [smell](https://en.wikipedia.org/wiki/Code_smell) to it. – user3386109 Aug 18 '16 at 23:25
  • 2
    Something like `int* pNumber1 = get_number1();` does **not** even belong into a header (well, inside an `inline` function, but that is a different subject)! – too honest for this site Aug 18 '16 at 23:26
  • And `static` is not the same as _static storage duration_. – too honest for this site Aug 18 '16 at 23:28
  • Thank you for your comments everyone. @user3386109 In short, this is for an embedded system application - I am trying to program a linked list for a DMA controller and wanted to move linked list initialization into it's own header. The `static struct` definition is in the DMA configuration file - and I just didn't want to clutter it with linked list initialization. Do you think there are any fundamental mistakes that I made in doing so? – avg Aug 19 '16 at 21:32
  • @agrus Headers are for (extern) declarations, data type definitions, and macros. Initializations (code) and global variables do not belong into a header. – Petr Skocik Aug 19 '16 at 21:35
  • @PSkocik That makes sense - thank you for clarifying this for me! – avg Aug 19 '16 at 21:39
  • My crystal ball shows a setter: `set_numbers(int num1, int num2, int num3)`. Without knowing all the details, I can't do better than that. – user3386109 Aug 19 '16 at 21:42
  • @agrus Forget the accessors and static. You want just one `struct myStruct myStructInstance = {/*the values*/};` in a c file, `extern struct myStruct myStructInstance;` in a header, and that's absolutely it. 2 lines of code. – Petr Skocik Aug 19 '16 at 21:59

2 Answers2

1

I've read a few answers as to why we cannot use non-constant expressions when initializing variables with static storage duration, however I do not understand how this relates to my code.

A function call is a non-constant expression.

int* pNumber1 = get_number1();

The above code is trying to initialize a global variable with a non-constant expression.

jxh
  • 69,070
  • 8
  • 110
  • 193
  • So this rule also applied to global variables, not just static ones? – avg Aug 18 '16 at 23:23
  • Global variables have static storage duration. – jxh Aug 18 '16 at 23:23
  • @jxh: `static` is not the same as _static storage duration_. – too honest for this site Aug 18 '16 at 23:30
  • 1
    Related, but not quite a dup: http://stackoverflow.com/q/17182648/315052 – jxh Aug 18 '16 at 23:58
  • Thank you for your comments and suggestions. I will take a look at what the difference is. @jxh Could you please suggest a better way to go about this piece of code? I am trying to set up a linked list in a separate header, and it needs access to the addresses of a `static struct` members in order to know where to store the information. Thank you! – avg Aug 19 '16 at 21:31
  • Call a function to set up the linked list. – jxh Aug 19 '16 at 21:35
0

You simply can't call code in the global scope.

However, you could easily accomplish the same thing as what you appear to be trying to do by simply extending myHeader.h with:

extern int *pNumber1, *pNumber2, *pNumber3;

and then allocating and initializing these in file.c with:

int *pNumber1 =  &myStructInstance.number1,
    *pNumber2 =  &myStructInstance.number2,
    *pNumber3 =  &myStructInstance.number3;
Petr Skocik
  • 58,047
  • 6
  • 95
  • 142