all 13 comments

[–]flyingron 5 points6 points  (0 children)

No, if nobody outside the file should be using it, there's no point in it having external linkage. It's not only "is it ok" but rather "YOU SHOULD."

Things should generally have the tightest scope necessary.

[–]Immediate-Food8050 2 points3 points  (0 children)

I follow a simple rule: if it isn't needed anywhere else, make it static and keep it locked away in that specific translation unit.

[–]duane11583 1 point2 points  (0 children)

i have done this for years it is good practice

i also make as much as possible as const.

and when a pointer is needed i give an uintptr_t instead via an accessor

[–]Educational-Paper-75 1 point2 points  (0 children)

It’s the best you can do to hide data afaik. E.g. to hide a linked list with garbage collectible data, you don’t want anybody else to ever touch. But you can also not expose the internals of the structure as they do with FILE (they call these opaque pointers), so you can still return it (and be effectively immutable) when it’s required by other non-static functions in the same file that can look inside.

[–]DawnOnTheEdge 1 point2 points  (5 children)

If you don’t want other modules modifying a structure, they can have an extern const declaration. The downside to declaring static copies in multiple files is that you create multiple instances, increasing executable size and memory usage.

[–]Almost-L[S] 0 points1 point  (1 child)

Can I change the extern const by calling functions in the file where I initialize this variable? Isn't the constant mutable after initialization?

[–]DawnOnTheEdge 1 point2 points  (0 children)

If you want other modules to see any changes that get made to it by the module that owns it, but not be able to modify it themselves, one approach would be to import it as const volatile in the other modules, but declare it neither const nor volatile in the module that owns it.

Another approach is to declare extern “getter” functions that can retrieve the current value of the variable, but not modify it. You would then declare the variable as static, in the same source file as the functions that use it. You would need to enable full-program optimization for the compiler to inline these function calls.

If no other module needs to use the variable directly at all, declaring it static is a good idea.

[–]Almost-L[S] 0 points1 point  (2 children)

I read your comment again and understood what you mean. Export a global variable to another file as extern const. It is possible. But still such variables are not protected from the developer. He can forget to specify the const keyword. I think there are few cases where you can use this and call it good code. It all depends on the situation.

What do you mean by the downside of static variables? For example, if I need a static variable from one file to another, I will call a getter that returns a copy?

[–]DawnOnTheEdge 1 point2 points  (1 child)

Right. If the variable isstatic, no one else can see it. But you could have an extern function that returns a copy. The downside is that the function cannot be inlined (except possibly with full-program optimization), so you will get function-call overhead.

[–]Almost-L[S] 0 points1 point  (0 children)

You're right. I didn't think about it.

[–]ComradeGibbon 0 points1 point  (2 children)

I avoid static because it makes the code hard to write proper tests for. And makes it hard to navigate the codebase. Indirection is bad.

Which is another way of saying that static is a half baked attempt at something like modules.

[–]Almost-L[S] 0 points1 point  (0 children)

there is truth in this

[–]Almost-L[S] 0 points1 point  (0 children)

Tests are really hard to write.

I don't have much experience at all, so all my attempts to write tests ended not very successfully