-1

There is an exisiting C-project with some modules. Each module has some global variables and some module global variables. We have naming conventions like MODULENAME_varname for a global variable declared by a module and Modulename_varname for a module global variable

Can I expect any troubles if i want to introduce structs for the corresponding global and module global variables like

struct{
 int  moduleId;
 type1 member1;
 type2 member2;
 ...
} MODULE

and

struct{
 int  moduleId;
 type1 member1;
 type2 member2;
 ...
} Module

I prefer that much more than having a bunch of unstructured variables. The idea is to have for example listing of all membervariables with an ide for more comfortability or just using functions in the sense of

log(MODULE.moduleId,offset(MODULE,member1))
floquet22
  • 323
  • 2
  • 15
  • To any close voters: This is *not* opinion based question. Some rules of C and common linking techniques make this answerable. – user694733 Feb 02 '16 at 13:44

1 Answers1

1

It can increase memory usage, for both RAM and program code.

Structure padding

Most architectures require that variables are somehow aligned. For example 32-bit variables may have to be aligned to addresses divisible by 4 to have efficient access.

Structure members are required to be in order they are declared. This means that compilers may need to add padding to keep data access fast.

struct { // Structure aligment is 4, to keep 'a' aligned
    uint32_t a;
    uint8_t b;
    // Compiler inserts 3 byte padding here to keep 'c' aligned
    uint32_t c;
    //... other data here
} Module;

Compilers can arrange "free" variables in memory in a way that is space efficent. For structures you need to do this manually. Usually this is done by ordering members from largest to smallest, or opposite.

Note that structre packing that many compilers offer is not solution for this. It typically decreases performance and/or increases program size.

Variable placement

I am simplifying this but:

Typically globals are divided in 2 groups: zero initialized and value initialized (other than zero). Before starting main, these both have to be initialized.

For zero initialized variables linker typically just groups them together in one location, and then does one big memset to set all bytes to zero in that area before calling main function.

Value initialized variables are similarly grouped in other location and then at program startup one big memcpy is done to copy initial values from program memory (arranged in same order) on your variables.

If you combine all variables to struct, then you are forcing all initial values to be copied from program memory if any of the values is non-zero.


If you are on desktop machine, these might not be problem. However, on embedded system where memory is tight, these have to be taken into consideration.

Note that I am not saying that this is a bad idea. Just keep structures modular too and avoid massive monolith structures.

user694733
  • 15,208
  • 2
  • 42
  • 68