Initialising a byte array by overlaying union-style (without a union instance) - Page 1
Forum section: electronics / general

author: 741
author_rank: Frequent Contributor
timestamp: June 12, 2020, 10:52:33 am
content: I have an existing code base which assumes an variableuint8_t gEEPersistentData;That is, logically speaking, EEPROM is treated like a "byte array".Mindful, of course of packing, alignment and other "gotchas" I could do this kind of thingtypedef union{Tpwm selectedPwm; //A|Buint8_t gEEPersistentData;}tEE_Config;tEE_Config eeConfig;But that means editing a generic code base to work with eeConfig.gEEPersistentData. Existing projects would have to declare a dummy union just so they can compile.For the simple array I can do thisuint8_t gEEPersistentData = {1,2, 0x20, 9, 65}; //etcIs there a syntax that allows me to cast a union as an array, and use that for intiialising? Something like thisgEEPersistentData = (cast of some type)(Tpwm{.period = 40,.duty = 20,.phase = 20});To summarise: I'd like an application-specific "data-structure" data to set up an generic byte arrayI do not want to alter the byte array declaration becuase that would break other projectsThe obvious union solution does not quite work here it would seemPerhaps, if I am prepared to ammend existing projects, I could start by typedef-ing the array, which could give me a type to cast "into"?

author: Kalvin
author_rank: Super Contributor
timestamp: June 12, 2020, 12:37:45 pm
content: Typically one would typedef a new data structure, and then assign a const pointer to point to that specific memory location (eg. the pointer to point to the address of gEEPersistentData, so that the two variables are forming effectively an union). Alternatively, one would typedef a new data structure and then create a new variable with an absolute address (ie. the address of gEEPersistentData).

author: 741
author_rank: Frequent Contributor
timestamp: June 12, 2020, 12:56:01 pm
content: That sounds workableI could require user code to define the pointerpEEPersistentDataThen the user can initialise it with the address of their arbitrary data structure.

author: Nominal Animal
author_rank: Super Contributor
timestamp: June 12, 2020, 05:41:36 pm
content: You cannot cast an intialization expression to another type in a way that would achieve what you want, but you can use an union and initialize a variable of that union type using whichever member you want. Then, you can use the preprocessor to mangle the name seen by userspace, into a reference of a member of that union.So, if you have an existing codebase that accesses the EEPROM data throughgEEPersistentDatabut you want to embed it in an union or a structure (or a combination):Code:union {Tpwm selectedPwm;uint8_t data;} eeConfig = { .selectedPwm = { .period = 40, .duty = 20, .phase = 20 } };#define gEEPersistentData (eeConfig.data)Here,sizeof gEEPersistentData == _EEPROMSIZE, and the type ofgEEPersistentatais an array ofuint8_t. It is perfectly okay to grab its address, for example.If the structure is declared and initialized in user code, but accessed in your/library code, you can put in a header file used by both user and library code:Code:typedef union {Tpwm selectedPwm;uint8_t data;} TEEConfig;#define DECLARE_EEPROM_PWM(spec...) \TEEConfig eeConfig = { .selectedPwm = { spec } };#define DECLARE_EEPROM_DATA(spec...) \TEEConfig eeConfig = { .data = { spec } };#define gEEPersistentData (eeConfig.data)extern TEEConfig eeConfig;and library code can happily access the_EEPROMSIZEbytes in arraygEEPersistentData, as long as one of the source objects declares the EEPROM, using e.g.Code:DECLARE_EEPROM_PWM(.period=40, .duty=20, .phase=20);or (equivalently if those Tpwm fields are all just bytes in that order)Code:DECLARE_EEPROM_DATA(40, 20, 20);This is pure ANSI C/ISO C89, and should work even with slightly limited or wonky C compilers just fine. In case you wonder, yes, it is legal to haveextern Type Var;and then defineType Var = ...;you do not need to have separate header files for "user code" and "library code".