Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is there anything wrong with using static const structs to limit name collisions of constants in C?

For example, if I were to create a hierarchical static const struct like this in a header (.h) file:

static const struct {
    struct {
        char STATIC /* = 0 */;
        char DYNAMIC /* = 1 */;
    } ALLOCATION;
    struct {
        char TABLE /* = 0 */;
        char LIST /* = 1 */;
        char TREE /* = 2 */;
    } STRUCTURE;
} FOO_STRATEGY = { {0, 1}, {0, 1, 2} };

foo_t *foo_create(char allocation_strategy, char structure_type);

Which would then be used something like this:

foo_t *foo = foo_create(FOO_STRATEGY.ALLOCATION.STATIC, FOO_STRATEGY.STRUCTURE.TREE);

I guess I have a two-part question:

  1. Does this work as one would expect?
  2. Why don't other people do this?
like image 916
Matt Avatar asked Jan 27 '15 22:01

Matt


People also ask

Can we use static const in C?

const means that you're not changing the value after it has been initialised. static inside a function means the variable will exist before and after the function has executed. static outside of a function means that the scope of the symbol marked static is limited to that . c file and cannot be seen outside of it.

Does const need to be static?

Constant. The const keyword converts nothing more but a constant. The specialty of these variables is that they need to have a value at compile time and, by default, they are static. This default value means that a single copy of the variable is created and shared among all objects.

Can static variables constant?

It's like a global variable that every instance of the class can access. But a static variable is not constant because it can be changed at any time.

Is it static const or const static?

They mean exactly the same thing. You're free to choose whichever you think is easier to read. In C, you should place static at the start, but it's not yet required.


2 Answers

I see four possible problems. If you don't care about any of this, go for it.

  1. You lose the ability to do things like this example, where enum values are used to "name" indices into an array, and the last entry in the enum gives array size automatically.

    typedef enum {
       COLOR_RED,
       COLOR_GREEN,
       COLOR_BLUE,
       NUM_COLORS  
    } Color;
    
    
    int myPallete[NUM_COLORS];
    myPallete[COLOR_RED] = 0xf80000;
    

    There are likely other ways you might use a #define or enum as a constant in such a way that your approach doesn't work in C. This was just the first to come to mind.

  2. Declaring the struct in the header that way puts a copy of the struct in every object file generated. The wasted memory makes this unfriendly to deeply embedded systems where 5 bytes or RAM wasted per object file would suck. Putting your structs in ONE ".c" file and declaring it in the header with extern might help here.

  3. Nobody else does this, so you're creating code that will trip up anybody else looking at your code for the first time, though I imagine it would not be hard to adjust. I don't care what your opinion is here. If multiple commentators said this would be confusing, you've already confused those people.

  4. This does little (maybe nothing?) to prevent name collisions. It makes no difference whether a header instantiates this struct or does #define FOO_STRATEGY. Anything that includes that header has equal possibility of name collisions if you use good prefixes on enum/#define values.

like image 146
Brian McFarland Avatar answered Oct 20 '22 03:10

Brian McFarland


People don't do this because that's what enum is for.

like image 44
Doug Currie Avatar answered Oct 20 '22 02:10

Doug Currie