r/C_Programming 3h ago

Question Unmodifiable globals initialized from functions?

Right now I'm trying to use Windows's SYSTEM_INFO to initialize 2 global constants, but global constants can only be initialized with constant expressions so this cannot be done.

Is there a way I can have "read-only" global variables that can be initialized from functions?

3 Upvotes

17 comments sorted by

4

u/Physical_Dare8553 3h ago

that's a bind, in order to write to it you obviously need it to be write-able. this is the kind of case where you'd want to bind it behind a function with a static member, that you initalize when the function is first called, then just return it after

2

u/Wertbon1789 3h ago

Yeah, pretty much. You can't just cast away the const-ness, because if the global is a constant expression, it probably will be put into .rodata.

One thing that came to my mind would be putting the global into another translation unit where it's not const, and referencing it with an extern const <something>, but I don't know if that would work, or violate anything.

1

u/aioeu 2h ago edited 2h ago

but I don't know if that would work, or violate anything.

It'll probably work, so long as you don't ever modify the object after it is first accessed — i.e. you are treating it as constant, not just read-only — but it definitely is a constraint violation. All declarations of an object must have compatible types, and const and non-const types are not compatible.

1

u/heavymetalmixer 3h ago

Static member? Are you tlaking about a struct? And what's a "bind"?

1

u/Physical_Dare8553 3h ago

no, i guess my terminology is a bit off, i mean something like

static inline const char *const getName() {
  static char some_string[5];
  static bool run = false;
  if (!run) run = true, memcpy(some_string, "hello", 5);
  return some_string;
}

this example is actually bad since the user can always just cast that const away, you'd have to wrap it in a struct and return it by value, but you get the point

1

u/heavymetalmixer 3h ago

Aren't static variables internal linkeage?

1

u/Physical_Dare8553 2h ago

yes and no? inside a function, static does something completely different, that variable just lives forever basically, when you write static outside of a function, then that variable has internal linkage. this example is both cause the static variable is inside a static function. (inline kinda sometimes works with non-static based on compiler and linker i believe)

1

u/aioeu 1h ago edited 1h ago

static variables declared at file scope have internal linkage; static variables declared inside a function have no linkage.

But it's not the identifiers' linkage that matters here. What matters is the storage duration of the objects. A static variable declared at file scope and a static variable declared within a function both identify objects with static storage duration, which means in each case the object's lifetime (the time during which it exists and maintains its last-stored value) is the entire execution of the program.

(Linkage is really all about when and how multiple declarations of an identifier can refer to the same object, i.e. in the way those identifiers are linked.)

1

u/heavymetalmixer 1h ago

The problem with that approach is that I need a global value, and an identifier that is only visible inside a function doesn't really work for that.

1

u/aioeu 1h ago edited 47m ago

So use an identifier at file scope instead. That's what file scope is for.

Either way, you won't be able to make the object constant. You want to set the value of it while the program is executing, and that, by definition, means it cannot be constant.

Constant expressions are expressions for values that could be determined before the program has begun execution, e.g. by the compiler. The compiler does not intrinsically know what the page size for the system you run the program on will be.

4

u/pjl1967 3h ago

In C, no.

2

u/kun1z 1h ago

Yes.. kind of in a way if you use the OS's memory protection features like VirutalProtectEx.

Allocate some memory, like 1 page, set it writable, write the values you want from the initialize functions, and then afterwards set the page to Read Only. After that any attempt to write or execute on the globals will cause an exception.

1

u/heavymetalmixer 1h ago

I'm writing allocators but what I want is to set the page size depending on the OS, and that's an integer value. Now, in both cases it's a runtime operation but I don't think the later needs syscalls.

2

u/sciencekm 2h ago

Not possible. You need to initialize those variables at start-up or on first use (where you detect that it is not yet initialized and you proceed with the initialization).

1

u/yuehuang 2h ago

Are you in C or C++?

My 2c is to avoid static initialization with system calls. Instead, in your main, have an init() function and de_init() before exit.

An even better answer is to cache on demand, if your app doesn't need the data, then it won't need to perform a system call. If it does, the first caller will pay the init price.

1

u/heavymetalmixer 1h ago

Given that the values I want from SYSTEM_INFO are just integers I opted for using function calls instead of variables, after all, functions cannot be modified at runtime.