IAR EWARM (ICC) - Expression must have a constant value - c

I'm trying to compile the following C code using IAR EWARM but I'm getting three compilation errors (Error[Pe028]: expression must have a constant value). See below:
#include<stdio.h>
#include<stdlib.h>
#include<stdint.h>
typedef uint8_t I2C_BusIdentifier;
typedef uint8_t I2C_SlaveAddress;
typedef enum {
I2C_BUS_STATE_UNINITIALIZED = 0,
I2C_BUS_STATE_GPIO_HARDWARE_READY,
I2C_BUS_STATE_READY_TO_OPERATE,
} I2C_BusState;
typedef struct BUS_I2C_BUS_INSTANCE_TYPE {
I2C_BusIdentifier BusIdentifer; // 0 for I2C0, 1 for I2C1
I2C_BusState CurrentState; // bus status
} I2C_Bus; // I²C Bus Instance Type, I2C_BusInstanceType
typedef struct DEVICE_I2C_GENERIC {
I2C_Bus* DeviceBusPointer;
I2C_SlaveAddress DeviceAddress;
} I2C_Device;
// inherits from I2C_Device
typedef struct DEVICE_ADC123 {
I2C_Device Device;
} ADC123_Device;
#define NUMBER_OF_I2C_PORTS 2
static I2C_Bus g_I2C_Bus[NUMBER_OF_I2C_PORTS] = {
{ 0, I2C_BUS_STATE_UNINITIALIZED, },
{ 1, I2C_BUS_STATE_UNINITIALIZED, },
};
I2C_Bus* const g_I2C_BusPtr_Port0 = &(g_I2C_Bus[0]);
I2C_Bus* const g_I2C_BusPtr_Port1 = &(g_I2C_Bus[1]);
const ADC123_Device g_Device_ADC123_U14 = {
{ g_I2C_BusPtr_Port0, 0xAE, }, // <--- Error[Pe028]: expression must have a constant value
};
const ADC123_Device g_Device_ADC123_U15 = {
{ g_I2C_BusPtr_Port1, 0x8A, }, // <--- Error[Pe028]: expression must have a constant value
};
const ADC123_Device g_Device_ADC123_U9 = {
{ g_I2C_BusPtr_Port1, 0xAA, }, // <--- Error[Pe028]: expression must have a constant value
};
#define NUMBER_OF_ADC123_DEVICES 3
const ADC123_Device* g_ADC123_Array[NUMBER_OF_ADC123_DEVICES] = {
&g_Device_ADC123_U14,
&g_Device_ADC123_U15,
&g_Device_ADC123_U9,
};
int main(void)
{
while(1);
}
However, everything compiles OK if I use the g_I2C_Bus addresses directly instead of through the g_I2C_BusPtr_PortX pointers:
const ADC123_Device g_Device_ADC123_U14 = {
{ &(g_I2C_Bus[0]), 0xAE, },
};
const ADC123_Device g_Device_ADC123_U15 = {
{ &(g_I2C_Bus[1]), 0x8A, },
};
const ADC123_Device g_Device_ADC123_U9 = {
{ &(g_I2C_Bus[1]), 0xAA, },
};
I want to use the const pointers (g_I2C_BusPtr_Port0, g_I2C_BusPtr_Port1) because they are extern'd in a .h file, whereas the array (g_I2C_Bus[]) will not be exposed globally but static in a specific .c file.
Why is the compuler unhappy about this when the definitions/values should be equivalent since they reference the same thing?

This is a limitation with C language. Values of variables, like
int const a = 1;
cannot be used in constant expressions, like as initializers:
int b = a; /* Will not work */
Not even with const qualifier. Reasoning is that compiler cannot know values of variables, even if it would seem completely trivial. Variable with const is not a constant in C, it's only variable which cannot be changed by you.
Addresses of global variables are a different matter. Linker complete control where these variables are located, and can use the same information for initializers.
Work-around is to use preprocessor:
#define g_I2C_BusPtr_Port0 (&(g_I2C_Bus[0]))

In case it is not clear from the other answers already; the correct code organization is:
// stuff.h
//
extern I2C_Bus *const g_I2C_BusPtr_Port0;
extern I2C_Bus *const g_I2C_BusPtr_Port1;
and then:
// stuff.c
//
#include "stuff.h"
I2C_Bus* const g_I2C_BusPtr_Port0 = &g_I2C_Bus[0];
I2C_Bus* const g_I2C_BusPtr_Port1 = &g_I2C_Bus[1];
const ADC123_Device g_Device_ADC123_U14 =
{ { &g_I2C_Bus[0], 0xAE } };
and so on.

Intializers for a static object must either be a constant expression or a string literal, if for example ADC123_Device g_Device_ADC123_U14 was a automatic variable then there would be no error, for example if you declared it in main. We can see this by going to the draft C99 standard section 6.7.8 Initialization which says:
All the expressions in an initializer for an object that has static storage duration shall be
constant expressions or string literals.
The reason why the second case works is that constant addresses are allowed, we can see this from 6.6 Constant expressions which says:
More latitude is permitted for constant expressions in initializers. Such a constant
expression shall be, or evaluate to, one of the following:
and includes the following bullet:
an address constant, or

Related

initialize flexible array members at compile time

I'm trying to optimize boot-time and run-time of an embedded application, and to do that, I'd like to initialize some constant flexible array members at compile time. I've found a few posts that say you must use malloc, but theoretically, it should be possible to do this without...
As an example, say I have:
typedef struct _foo_t {
foo_t *next;
int num_bars;
bar_t bars[];
} foo_t __attribute((__packed__));
And I have literally have several million instances of foo_t. I then have a script to generate a header file with all the information. So I might have something like this:
const foo_t foo1 = {.next = &foo2, .num_bars = 2};
const bar_t foo1_bar1 = {...};
const bar_t foo1_bar2 = {...};
foo_t *const first_foo = &foo1;
But, the problem with this is that the compiler spec does not guarantee that &foo1_bar1 is not guaranteed to be at &foo1.bars[0]. I'm wondering if there's any trickery anyone knows to force the fooX_barY members to be placed in the correct locations in memory.
Note that my goals are:
reduce boot time by avoiding unnecessary mallocs
reduce memory thrashing by having the bar's typically in the same cache pages as corresponding foos
reduce memory requirements by not having pointers to bars
If anyone knows of any good tricks to do this, I'd love to hear them
GCC and clang seem to support standard initializers for flexible arrays so if you can restrict yourself to these compilers, you only need to add casts for const removal. The initializer does not have to use designated members, classic intializers work fine at least for clang.
This extension is actually quite consistent with the C syntax for array initializers where the length of the array can be omitted if it can be determined from the initializer.
For compilers that do not support this syntax, here is a trick to achieve what you want:
//----------------
// you can move these to foo.h
typedef int bar_t;
typedef struct foo_t {
struct foo_t *next;
char name[8];
int num_bars;
bar_t bars[];
} foo_t;
extern foo_t * const first_foo;
extern foo_t * const second_foo;
//----------------
// The definitions can be generated automatically into a separate module
// disable warnings cf: https://stackoverflow.com/a/55877109/4593267
#pragma GCC diagnostic ignored "-Wcast-qual"
#pragma clang diagnostic ignored "-Wcast-qual"
// Trick for VLA initialization
#define foo_t(n) struct { foo_t *next; char name[8]; int num_bars; bar_t bars[n]; }
// using a classic structure initializers
static const foo_t(2) foo2 = { 0, "foo2", 2, { 1, 2 }};
static const foo_t(1) foo1 = { (foo_t *)&foo2, "foo1", 1, { 42 }};
foo_t * const first_foo = (foo_t *)&foo1;
// using a compound literal
foo_t * const second_foo = (foo_t *)&(foo_t(3)){ 0, "foo3", 3, { 10, 20, 30 }};
// using gcc / clang flexible array initializer
#pragma clang diagnostic ignored "-Wgnu-flexible-array-initializer"
static foo_t third_foo = { 0, "foo4", 2, { 1, 2 }};
//----------------
// Test framework
#include <stdio.h>
void foo_print(const char *name, foo_t *p) {
printf("%s: {\n", name);
for (; p; p = p->next) {
printf(" { \"%s\", %d, { ", p->name, p->num_bars);
for (int i = 0; i < p->num_bars; i++)
printf("%d, ", p->bars[i]);
printf("}},\n");
}
printf("}\n");
}
int main() {
foo_print("first_foo", first_foo);
foo_print("second_foo", second_foo);
foo_print("third_foo", &third_foo);
return 0;
}
Output:
first_foo: {
{ "foo1", 1, { 42, }},
{ "foo2", 2, { 1, 2, }},
}
second_foo: {
{ "foo3", 3, { 10, 20, 30, }},
}
third_foo: {
{ "foo4", 2, { 1, 2, }},
}
Your attempts using certain ordering of the related variables is prone to error as the compiler does not need to allocate the variables at the place you want.
The only way to use static variables instead of dynamically allocated memory is to add the members of that flexible array directly into the initializer of your variable:
const foo_t foo1 =
{
.next = &foo2,
.num_bars = 2,
.bars =
{ [0] = {...},
[1] = {...}
}
};
Dedicated initializers are optional.
At least for GCC this should work.
Unfortunately it is not possible to use the common (sizeof(arr)/sizeof(arr[0])) trick to get the number of elements in an array:
foo_t foo1 =
{
.next = &foo2,
.bars =
{ [0] = 1,
[1] = 2
},
.num_bars = sizeof(foo1.bars)/sizeof(foo1.bars[0]),
};
test.c:21:21: error: invalid application of ‘sizeof’ to incomplete type ‘bar_t[]’ {aka ‘int[]’}
21 | .num_bars = sizeof(foo1.bars)/sizeof(foo1.bars[0]),
| ^

error: initializer element is not constant in C [duplicate]

This question already has answers here:
Error "initializer element is not constant" when trying to initialize variable with const
(8 answers)
Closed 3 years ago.
Here i am trying to make state machine where FsmHdlr should call a appropriate function based on state and event. What i am getting the above error. How to resolve this.
S16 handleParamReqEvt(void)
{
/* doing something */
RETVALUE(ROK);
}
S16 handleParamRspEvt(param_resp *paramRsp)
{
/* doing something */
RETVALUE(ROK);
}
typedef enum{
IDLE,
CONFIGURED,
MAX_STATE
}STATE;
/* Events in CL */
typedef enum{
PARAM_REQ,
PARAM_RSP
MAX_EVENT
}EVENT;
param_resp *paramMsg;
S16 FsmHdlr[MAX_STATE][MAX_EVENT] =
{
{
/* PHY_STATE_IDLE */
handleParamReqEvt(), //error :initializer element is not constant
handleParamRspEvt(paramMsg) //error: initializer element is not constant
}
};
It sounds like you don't actually want to call the function during initialization (which you can't do for static storage variables anyway, as you've discovered). It sounds like you are building a dispatch table. What you want is called a function pointer.
This how one uses function pointers:
int foo(void) { ... }
int main(void) {
int (*bar)(void) = foo;
bar(); // Calls foo
}
Since the parameters vary based on the type of the event, a 2d array doesn't make much sense. I'd use the following in your case:
S16 fsm_hdrl_idle_param_req(void) { ... }
S16 fsm_hdrl_idle_param_rsp(ParamRsp *param_rsp) { ... }
S16 fsm_hdrl_conf_param_req(void) { ... }
S16 fsm_hdrl_conf_param_rsp(ParamRsp *param_rsp) { ... }
typedef S16 (*FsmReqHdlr)(void);
typedef S16 (*FsmRspHdlr)(ParamRsp*);
typedef struct {
FsmReqHdlr fsm_req_hdlr;
FsmRspHdlr fsm_rsp_hdlr;
} FsmHdlrs;
FsmHdlrs fsm_hdlrs_by_state[MAX_STATE] = {
{ fsm_hdrl_idle_param_req, fsm_hdrl_idle_param_rsp },
{ fsm_hdrl_conf_param_req, fsm_hdrl_conf_param_rsp },
};
Later:
fsm_hdlrs_by_state[state].fsm_req_hdlr();
fsm_hdlrs_by_state[state].fsm_rsp_hdlr(param_rsp);
You could declare pointer to FsmHdlr[MAX_STATE][MAX_EVENT] as a global variable.
S16 (*FsmHdlr)[MAX_STATE][MAX_EVENT] = NULL;
Somewhere in main function allocate the memory to the global pointer as below.
FsmHdlr = malloc(sizeof(S16 [MAX_STATE][MAX_EVENT]));
Then use memcpy to copy array compound literal as below.
memcpy(FsmHdlr,
(S16 [MAX_STATE][MAX_EVENT]) {
{
/* PHY_STATE_IDLE */
handleParamReqEvt(), handleParamRspEvt(paramMsg)
}
},
sizeof((S16 [MAX_STATE][MAX_EVENT]) {
{
/* PHY_STATE_IDLE */
handleParamReqEvt(), handleParamRspEvt(paramMsg)
}
})
);
And dereference as below,
(*FsmHdlr)[0][0];//to access 1st element
(*FsmHdlr)[0][1];//to access 2nd element
You cannot initialise array during declaration using values, what are unknown while compilation.
And, your initialization values are values returned by handleParamReqEvt() and handleParamRspEvt(...), what are unknown.
I suppose that you are thinking about pointers to these functions, nor function values.
So, you should use function names instead of function calls, like below:
S16 FsmHdlr[MAX_STATE][MAX_EVENT] =
{
{
/* PHY_STATE_IDLE */
handleParamReqEvt, //initializer element is NOW constant
handleParamRspEvt //initializer element is NOW constant
}
};
Unfortunately, this will not compile because of wrong array type - now it is not S16[][] (or S16**) like before.
Additionaly, both pointers are pointers of different types:
- first is S16 ( * )();
- second is S16 ( * )(param_resp*);
Fortunately, you can store them both as void* (pointer to anything), but remember that you MUST PROPERLY CAST them before usage.
For cast simplification you can declare the types of these function using typedef directive.
So, the final form of declaration+initialization and usage will be:
// declaration + initialisation of array
void* FsmHdlr[MAX_STATE][MAX_EVENT] =
{
{
/* PHY_STATE_IDLE */
handleParamReqEvt,
handleParamRspEvt
}
};
// declaration of types
typedef S16 (*reqEvt_ptr)(); //signature of handleParamReqEvt()
typedef S16 (*rspEvt_ptr)(param_resp*); //signature of handleParamRspEvt(param_resp*)
// usage:
// handleParamReqEvt
reqEvt_ptr reqEvt = (reqEvt_ptr)FsmHdlr[/* index here */][PARAM_REQ]; // cast
S16 reqResult = reqEvt(); // call
// handleParamRspEvt
rspEvt_ptr rspEvt = (rspEvt_ptr)FsmHdlr[/* index here */][PARAM_RSP]; // cast
S16 rspResult = rspEvt(/* pointer to paramMsg here */); // call

C initializer element is not constant - pointers in struct

Code snippets appear below
/// System Parameters for the gateway
typedef struct {
bool mobile_gateway; // true = GPS receiver used, else false
uint16_t gw_ordinal_number; // Starting at 1, the ordinal gateway number
} CONFIG_SYSTEM_PARMS;
// Data types for the system parameters
typedef enum {
CFGPARM_TYPE_BOOL,
CFGPARM_TYPE_UINT,
CFGPARM_TYPE_INT,
CFGPARM_TYPE_DOUBLE,
CFGPARM_NUM_TYPES
} CONFIG_PARM_DATA_TYPES;
// These mnemonic names and data types correspond to the system parameters
#define SYS_PARM_MOBILE_GATEWAY_MNEM "MOBILEGW"
#define SYS_PARM_GATEWAY_NUMBER_MNEM "GWNUM"
#define SYS_PARM_MOBILE_GATEWAY_TYPE CFGPARM_TYPE_BOOL
#define SYS_PARM_GATEWAY_NUMBER_TYPE CFGPARM_TYPE_UINT
typedef struct {
char FILLER; // TODO - Define User Parms later...
} CONFIG_USER_PARMS;
static const uint16_t TOTAL_CONFIG_PARM_BYTESIZE = sizeof(CONFIG_SYSTEM_PARMS) + sizeof(CONFIG_USER_PARMS);
typedef struct {
const char *sysparm_mnemonic;
CONFIG_PARM_DATA_TYPES sysparm_data_type;
void *sysparm_data_ptr;
} CONFIG_PARM_LOOKUP_TABLE;
// ****************************************
static LT_LOGGER_DATA gateway_log_data;
static CONFIG_SYSTEM_PARMS *config_sys_parms_ptr = &gateway_log_data.config_system_parms;
// **************************************************
// Lookup table for the System Parms
//
// CAA: This is a stinking mess - There is no easy way to define &gateway_log_data.config_system_parms
// outside of the following initialization, so the result is more verbose than it should be
static const CONFIG_PARM_LOOKUP_TABLE config_parm_lookup_table[] = {
{ SYS_PARM_MOBILE_GATEWAY_MNEM, SYS_PARM_MOBILE_GATEWAY_TYPE, &config_sys_parms_ptr->mobile_gateway},
{ SYS_PARM_GATEWAY_NUMBER_MNEM, SYS_PARM_GATEWAY_NUMBER_TYPE, &gateway_log_data.config_system_parms.gw_ordinal_number},
// FILLER to mark end of list
{ "", 0, NULL}
};
The question is this:
Why, am I getting the error : initializer element is not constant (near initialization for 'config_parm_lookup_table[0].sysparm_data_ptr')
when the initializer for config_parm_lookup_table[1].sysparm_data_ptr is effectively using the same construct?
Obviously, I have a work-around, but it seems verbose.

Incorrect initialization of a structure instance with data from const char *[][]

I obtained the following compilation error:
error: initializer element is not constant
while using this code (divided into 3 files, as follows):
File 1
This array is used to easily switch between language versions of menu.
#define LANG_EN 0
#define LANG_PL 1
#define LANGUAGES 2
const char *const message[][LANGUAGES] = {
#define MSG_INTRO 0
/*0*/ { "Hello", "Witamy" },
#define MSG_MENU1 1
/*1*/ { "Option1", "Opcja1" },
#define MSG_MENU2 2
/*2*/ { "Option2", "Opcja2" },
};
File 2
This file contains,among others, the definition of the structure used:
struct _menuitem
{
const char *const text;
int action;
};
struct _menuitem const menu;
File 3
In main.c I initialize the structure:
#define PGM_STR(X) ((const char[]) { X })
const struct _menuitem const menu = {PGM_STR(message[MSG_INTRO][LANG_PL]), 0};
When I put any string in quotes (like "Testest") under PGM_STR macro then everything is fine.
Q: How should I initialize the struct with string data from the
const char *const message[][LANGUAGES]
so that it remains inline as shown above?
What am I doing wrong?
I know there are a lot of topics concerning this compilation error, but none of them actually concerns this type of array-structure combination.

Initializing structure by named members

I'm trying to wrap my head around the syntax provided in http://publib.boulder.ibm.com/infocenter/lnxpcomp/v7v91/index.jsp?topic=%2Fcom.ibm.vacpp7l.doc%2Flanguage%2Fref%2Fclrc03strin.htm :
struct
{
int a[5], b;
} game[] =
{
[0].a = { 1 },
[1].a[0] = 2
};
Ideally, I'd find some way to do the following:
struct
{
int a, b;
} foo =
{
.a = 4,
.b = 5
};
My reason for wanting to have a by-name initialization of a structure is that my own stucture has many members, so I want better clarity. I shouldn't just initialize them in separate statements because this is a performance-sensitive embedded application where the members are actually bitfields, so a single struct init generates fewer instructions than multiple member initializations.
Which C standard allows for by-name member init like that?
It's not immediately clear what you're asking, but with a c99 compiler, your first attempt could be written as
struct
{
int a[5], b;
} game[] =
{
[0] = {.a = { 1 }},
[1] = {.a[0] = 2}
};
I'm doing something similar in an embedded app under C99. I have a variable called phaseInstill that is "assigned" to a struct:
phaseInstill = (PhaseVolumeStatus)
{
.complete = false,
.ticksInstilled = 0,
.volumeInstilled = 0,
.volumeRemaining = instillVolume
};
Where PhaseVolumeStatus is defined as:
typedef struct
{
Value volumeRemaining; /*!> ml */
Value volumeInstilled; /*!> ml */
Value ticksInstilled; /*!> ticks */
bool complete;
} PhaseVolumeStatus;
I don't have a bitfield example handy, but I don't recall it working any differently in any other of my uses.

Resources