Static const struct vs static const of its members - Page 1
Forum section: electronics / general

author: ricko_uk
author_rank: Super Contributor
timestamp: March 17, 2021, 10:29:12 pm
content: Hi,is there any difference between these (i.e. placing "static const" at struct level, at variables level or both?Any pros or cons of any of them?Version Astatic const struct my_struct_A{char = "Hello";int a = 0;}Version Bstruct my_struct_B{static const char = "Hello";static const int a = 0;}Version Cstatic const struct my_struct_C{static const char = "Hello";static const int a = 0;}This also in reference to storing the variables in flash.Thank you

author: emece67
author_rank: Frequent Contributor
timestamp: March 18, 2021, 01:04:45 am
content: .

author: ajb
author_rank: Super Contributor
timestamp: March 18, 2021, 01:18:20 am
content: `static` has two meanings in C: for variables declared within a function, static qualification means they will retain their value between invocations of the function. For global variables, static qualification means those variables will not be accessible from outside the file they're declared in.In C qualifying a member of a struct as static doesn't make any sense. Static qualification of a struct will have different effects based on where the struct is declared, as above.`const` can be applied at either the struct level, and will apply to the entire struct, or at the member level, and apply to only that member. One thing to particularly watch out for is with pointers, where the application of const can be a bit surprising if you're not used to the way that C declarations work (which is admittedly kind of obtuse). If you have:Code:struct foo {const int * ptr;}The value of the integerpointed toby the pointer will be const, whereas with:Code:const struct bar {int * ptr;}thevalue of the pointer, that is, the memory location it targets, is const, because the struct that contains that pointer is const.To answer your question if you want the entire struct to be static const, then make the struct static const rather than every member. If you're typedefing the struct then you can leave the static/const qualification out of the typedef and then you can apply those qualifications to each instance as needed:Code:typedef struct my_struct_t {char string;int a;} my_struct_t;my_struct_t foo;const my_struct_t bar = {.string = "hello",.a = 42,}As far as getting variables to be stored in flash, this is dependent on the target and the compiler. const doesn't necessarily mean that a qualified variable will end up in flash, although this may be the default behavior in many compilers, including arm-gcc. There are also specific extensions you can use to explicitly place objects in particular parts of memory depending on the compiler--in GCC this would be a section attribute, which can also be used to place variables or other objects in specific areas of ram, for example in 'tightly coupled' memory regions that may offer improved performance. Other platforms, particularly architectures that don't have a contiguous memory layout between flash and ram, require additional steps to place data in flash and may require extra steps to read those values from flash. For example in AVR, you would need to use the PROGMEM and pgm_read_ family of macros for this.

author: ajb
author_rank: Super Contributor
timestamp: March 18, 2021, 01:29:20 am
content: Quote from: emece67 on March 18, 2021, 01:04:45 amNo, you can assign from one struct to another. In C a struct is not a real object unto itself, it's nothing more than a collection of member variables laid out in a chunk of memory, the name of the struct is just a convenient way to refer to that collection, and the declaration of the struct informs the compiler how those members are laid out. The size of the struct in memory is basically equal to the total size of its members (though there may be some gaps to maintain word alignment of each member depending on platform and compiler settings). Doing something like `my_struct_t foo = bar`, where bar is another my_struct_t is equivalent to a `memcpy(&foo, &bar, sizeof(my_struct_t))`, but with more convenient syntax. The caveat here, since the struct is copied byte-for-byte, is that this is a 'shallow' copy, and if there are pointers in the struct both structs will end up with the same pointer values, pointing to the same areas in memory, which may or may not be what you want.

author: DavidAlfa
author_rank: Super Contributor
timestamp: March 18, 2021, 02:27:48 am
content: Now I politely drop the bomb and leaveStruct name{ };typedef struct name{ };typedef struct name{ }name;

author: emece67
author_rank: Frequent Contributor
timestamp: March 18, 2021, 08:44:13 am
content: .

author: emece67
author_rank: Frequent Contributor
timestamp: March 18, 2021, 08:56:31 am
content: .

author: Nominal Animal
author_rank: Super Contributor
timestamp: March 18, 2021, 12:35:28 pm
content: The way to read C type specifications is to start at the name, split everything left of it at each *, and read the parts from right to left, with each * as "is a pointer to". Examples:const char *volatile foo;foois a volatile pointer to const char.char *const bar;baris a const pointer to char.volatile int * (*pointer_returner)(int);pointer_returneris a function pointer taking a single int as a parameter, and returns a pointer to a volatile int.Within each part, the order does not matter.const charis the same aschar const.constis a promise that the code will not try to modify the value; andvolatiletells the compiler some other (seen or unseen) code may change the value at any time.staticmeans the function or variable has file scope. Inside a function, in a variable declaration, it means that variable exists outside the function call, like global variables; but isn't accessible outside the function (because the declaration was inside a function). Outside the function it means the function or variable is not to be externally accessible (from other compilation units), only from within the current file (compilation unit). (File scope or compilation unit means the C source file being compiled, including all header and source files it #include's, and all header and source files those #include in turn; plus all include files the compiler is told to include.)

author: ejeffrey
author_rank: Super Contributor
timestamp: March 18, 2021, 03:59:23 pm
content: static is a red herring in this instance. static is a storage class specifier not a type qualifier. Thus static only applies to actual variables not types. None of your examples declare variables and so static is meaningless.

author: SiliconWizard
author_rank: Super Contributor
timestamp: March 18, 2021, 06:43:31 pm
content: Yeah, the example is not that relevant with the static qualifier IMO. But const and volatile, that can be a typical use.Now the general question of using qualifiers for struct members can be interesting, although I frankly very rarely do that.A const qualifier on an individual struct member just means that only this member is read-only. Same for volatile, it applies to one member instead of the whole struct.There is no difference that I know of between qualifying the whole struct, and individually qualifying ALL the struct members with the same qualifier(s).So again using qualifiers per struct member would make sense only if members do NOT all have the same qualifiers.Qualifiers on struct/type definitions (as oppposed to variable declarations) are to be used sparingly IMO and with a clear purpose. For instance, let's say you define some struct meant to hold some application parameters. This struct may be used to declare const variables (for fixed parameters for instance), but also for non-const variables (for parameters modifiable at run-time for instance), so in this case the qualifiers are best used ad-hoc with variable declarations and not at the struct definition level. Defining a struct/any type with a qualifier will mean all variables declared with this type will hold the same qualifier. Make sure this is really what you intend.