Difference between `@(rodata)` global and a constant?

what’s the difference between:

@(rodata)
DIVIDE_BY_255_TABLE := [256]f32{ /*...*/ }

and

DIVIDE_BY_255_TABLE :: [256]f32{ /*...*/ }

as in why would you pick one over the other

As far as I understand it:

Globals with @(rodata) go into a read-only section in the binary, usages reference it by pointer.

@(rodata)
DIVIDE_BY_255_TABLE := [256]f32{ /*...*/ }

Globals go into a data section when the binary is loaded, usages reference it by pointer.

DIVIDE_BY_255_TABLE := [256]f32{ /*...*/ }

Constants only “exist” at compile time and get turned into (in this example, a shit-ton) of instructions. This can really blow up your code size if you use it many times.

DIVIDE_BY_255_TABLE :: [256]f32{ /*...*/ }

If you want to check for yourself, put your example into godbolt.org and select the Odin compiler.

1 Like

As for the question of when to use one over the other. As was outlined in the previous comment, @(rodata) globals are variables that are simply put into the read-only section of the executable. You can, for example take an address - this variable exists in memory, when the program runs.

Constants, on the other hand do not exist in memory when the program runs. You can imagine the compiler simply taking the definition of the constant and copy-pasting them into every instance where it is used. It is not possible to assign to them, or take their address.

So I guess my outline would be:

  • Prefer using constants.
  • If you need it to be addressable, for example if you want to make a static table, use @(rodata) global variable.
1 Like