2

let's assume that we have below struct definitions:

typedef struct {
  uint8_t a ; 
} deepest_t ;  

typedef struct {
  deepest_t* deepest_ptr ;
} deeper_t ; 

typedef struct {
  deeper_t*  deeper_ptr ;
} deep_t ; 

typedef struct {
  void* data ;
} data_container_t ; 

and following initializations:

deepest_t deepest = {
  .a = 5, 
} ; 

deeper_t deeper = { 
  .deepest_ptr = &deepest, 
} ;

deep_t deep = { 
  .deeper_ptr = &deeper,
} ;

and now question, could you please tell me how to initialize void* data by usage of the designated initializer in order to void* data will point the deepest_t deepest. I've tried such a solution, but compiler is screaming that it is not a const value :

data_container_t data_container = {
  .data = &(((deeper_t*) deep.deeper_ptr)->deepest_ptr),
} ; 
Lazureus
  • 462
  • 4
  • 19
  • You cannot. Why do you think you should be able to? Initializers should be constant. An object value (`deep.deeper_ptr` in your case) is not a constant. Even if was just initialized with a constant, and did not have a chance to change yet, it is not a constant still. – n. m. could be an AI Apr 25 '13 at 14:41
  • 1
    As a tangent, the cast here is totally redundant, and your description does not match your code (you say you want to point `data` to `deepest` but the code tries to point it to `deepest_ptr`. Avoiding casts and `void*` will help minimize such things. – n. m. could be an AI Apr 25 '13 at 14:45
  • Do I really cannot do this ? But address of the `deepest` variable or adress in which `deepest_ptr` is located is known and it's const, and this is what I want to get. – Lazureus Apr 25 '13 at 14:45
  • Consider that `((deeper_t*) deep.deeper_ptr)->deepest_ptr` is a `deepest_t *`. Therefore, `&(((deeper_t*) deep.deeper_ptr)->deepest_ptr)` must be a `deepest_t **`. How can a `deepest_t **` point to a `deepest`, as your question requests? Don't use `_t` suffixes; That's reserved for the implementation. – autistic Apr 25 '13 at 14:46
  • 1
    You are not referring to an address of `deepest`. You are referring to something that is pointed to by a pointer stashed in `deep.deeper_ptr` and then taking the `deepest_ptr` member of that something and then taking an address of that member. If you want an address of `deepest`, say `&deepest`. – n. m. could be an AI Apr 25 '13 at 14:49
  • @n.m I don't want to go with the `&deepest`, because I'm assuming that only `data_container` will be externed in the header file. What I'm trying to accomplish here is casting to the `void*` some parts of the `deep_t deep` structure. In this case I want to cast instance of the `deepest_t` structure. If I succeed then in different file I'd like to cast `void *data` to particular data type and retrive data in which I'm interested in. – Lazureus Apr 25 '13 at 14:58
  • You can't use parts of a structure in an initializer because they are not constant. – n. m. could be an AI Apr 25 '13 at 15:06
  • @n.m. I disagree with you I can initialize like this: `.data = &deep.deeper_ptr` this will initialize my data pointer with the same address like `&deep` but if I will have `deeper_ptr2` or `deeper_ptr3` such a initialization like `.data = &deep.deeper_ptr3` will set data to &deep + some offset – Lazureus Apr 25 '13 at 15:11
  • You can use the *address* of `deep.deeper_ptr`. You cannot use its *value*. I think there's nothing more to say about it. – n. m. could be an AI Apr 25 '13 at 15:17
  • @n.m. yes exactly, and this is what I want to use for the `deepest_ptr` as well. – Lazureus Apr 25 '13 at 15:22
  • I got it. You want to use the value. **You can't**. – n. m. could be an AI Apr 25 '13 at 15:33
  • I agree that I cannot initialize `void* data` with value, but I can do something like this:`.data = &deep.deeper_ptr` and then in my function or wherever where I can see `data_container` something like this : `deeper_t** temp = data_container.data` and then `**temp` will point to the `deeper_t deeper`,please correct me if I'm wrong – Lazureus Apr 25 '13 at 15:41

2 Answers2

0

In here I believe you are keeping the address of deepest_ptr ..

data_container_t data_container = {
  .data = &(((deeper_t*) deep.deeper_ptr)->deepest_ptr),
} ;

So to retrieve it, you can do this ..

deepest_t * d = *((deepest_t**)(data_container.data));

printf(" %ud \n", (*d).a);

Since you can't use void* until you cast it ..

Here's a live execution

Khaled.K
  • 5,828
  • 1
  • 33
  • 51
0

If the initializer is used to initialize a variable of static storage duration, it should be a constant expression, and therefore you cannot do that.

If it is used to initialize a local non-static variable you are fine with this initializer:

data_container_t    data_container  = {
    .data   = (deep.deeper_ptr)->deepest_ptr,
};

That assuming you want what you say in your text ("point the deepest_t deepest").

What a constant expression is you can read it here: Details of what constitutes a constant expression in C?