1

hope everyone is doing great! I was trying to implement some lib in embbeded enviroment, where i need to use const pointers. Here is the code i was trying to do:

#include <stdio.h>

int a = 10;

typedef struct {
    void * const payload;
    int size;
} msg;

typedef struct {
    void * const payload2encode;
    int size2encode;
} encode_msg;

msg message[1] = {
    {
        /* payload */ &a, 
        0
    }
};

encode_msg encoded_message = {
    /* payload */ message[0].payload,
    0
};

int main(void){
    return 0;
}

but i'm getting the following error:

main.c:23:19: error: initializer element is not constant 23 |
/* payload */ message[0].payload,

If I change 'message[0].payload' to '&a' the code runs fine. I don't get why this is happening :(. Anyone know why?

Best reggards!

Mgoulart
  • 41
  • 3
  • 1
    Is it because of that diagnostic that you think you need to use a `const` pointer, or did you decide to declare `msg.payload` to be `const` for some other reason? Note well that although structure members *can* be `const`-qualified, that tends to make those structure types difficult to work with. – John Bollinger Sep 23 '22 at 13:39

2 Answers2

3

There are a lot of misconceptions here.

First of all, why do you need a "constant pointer"? This message here:

error: initializer element is not constant

Does not mean "the compiler wants a constant pointer", but rather "I want a a compile-time constant such as an integer constant expression". This has nothing to do with const at all in C (C++ is another story), but this:

A variable with static storage duration, like one declared at file scope outside any function, must be initialized with a constant expression. Such as an integer constant expression or in case of pointers the address of another variable. But it cannot be initialized to the value of a different variable. Simple example:

  int a = 0;
  int b = a; // error: initializer element is not constant

That's just how the language works. You could initialize a pointer to an address however, since address constants are constant expressions. That's why /* payload */ &a, works.

Next misconception: there is nothing called "constant pointer". There are:

  • pointers to read-only data, const type* name.
  • read-only pointers to read/write data: type* const name.
  • read-only pointers to read-only data: const type* const name.

For some reason you picked the second of these options (took a gamble?). It has limited uses, but one valid use of it is to declare read-only pointer variables in ROM on embedded systems with true ROM like flash.

Also we usually don't want to use qualifiers like const inside a struct on an individual member if we can avoid it. Because then the struct variable itself ends up with different qualifiers than it's members. Normally we want the whole struct to be const or nothing in the struct at all. In embedded systems we also need to consider if we want it to be stored in RAM or flash.

Regarding void*, they are not very suitable to use for any purpose in an embedded system. uint8_t* boiling down to a character pointer is much more useful, since it can be used to access any other type byte by byte. Whereas a void* has to be converted to another type before we can do anything meaningful with it. Type-generic programming in embedded systems is also a bad idea most of the time, since such systems should behave deterministically.

Lundin
  • 195,001
  • 40
  • 254
  • 396
1

encoded_message has static storage duration (because it's declared outside any function) and so must be initialized with a constant expression, and message[0].payload isn't (it's a const variable, but not a constant expression).

You can either declare encoded_message in a function (main, for instance), or, if your compiler supports it, make message const as well.

See also : Error "initializer element is not constant" when trying to initialize variable with const

Nelfeal
  • 12,593
  • 1
  • 20
  • 39
  • making `message` *const* does not help because `message[0].payload` would still be "non-constant" expression. Some compilers may support it but it is an extension. – tstanisl Sep 23 '22 at 14:32
  • @tstanisl Thanks, I couldn't find exactly why it worked. – Nelfeal Sep 23 '22 at 14:38