|
|
Subscribe / Log in / New account

File permissions in the kernel

File permissions in the kernel

Posted Aug 4, 2016 15:25 UTC (Thu) by epa (subscriber, #39769)
Parent article: File permissions in the kernel

Is there a reason these are done as #define instead of const int?


to post comments

File permissions in the kernel

Posted Aug 4, 2016 19:51 UTC (Thu) by k8to (guest, #15413) [Link] (14 responses)

There are reasons to prefer defines over const vars. A const int with global visibility occupies memory, while a define may not (it may become an operation immediate). There's also some readability value to the namespacing and practice of representing such symolic constant values consistently instead of picking different approaches depending upon the values. I'm sure there are more.

File permissions in the kernel

Posted Aug 5, 2016 5:47 UTC (Fri) by epa (subscriber, #39769) [Link] (9 responses)

Does a const int included via a header file occupy any memory? I assumed it would be inlined whenever used.

File permissions in the kernel

Posted Aug 5, 2016 6:35 UTC (Fri) by johill (subscriber, #25196) [Link] (6 responses)

It would consume memory in every C file that includes it and even break the link unless it was declared static.

File permissions in the kernel

Posted Aug 5, 2016 6:38 UTC (Fri) by johill (subscriber, #25196) [Link] (5 responses)

Oh, wait - const. That doesn't seem to be true then, sorry.

File permissions in the kernel

Posted Aug 5, 2016 6:41 UTC (Fri) by johill (subscriber, #25196) [Link] (4 responses)

Hmm, but looking further, that seems only due to the optimiser, and in fact without the static it does cause build errors. So it's not clear to me whether or not it'll be actually put into every file that doesn't use it, but if you *do* use it then it will consume memory.

File permissions in the kernel

Posted Aug 5, 2016 19:39 UTC (Fri) by xtifr (guest, #143) [Link] (3 responses)

This is one of the subtle differences between C and C++. Stroustrup didn't like the preprocessor, so he declared that a const of a fundamental type (at least) would be inherently inline. It can even participate in constant folding at compile time. He did this specifically so that you could declare consts instead of #defines. C didn't go this route.

In C, if you put "const int foo = 5;" in a header, and include it in multiple files, you'll get a link-time error about multiple definitions. In C++, this not only works, it's preferred.

This is something that can easily trip up a C++ programmer who isn't used to C. C++ books tend to emphasize that #defines are bad and you should use consts instead.

I'm guessing that epa works with C++ more often than with C. :)

File permissions in the kernel

Posted Aug 5, 2016 23:47 UTC (Fri) by Jonno (subscriber, #49613) [Link] (2 responses)

Actually, the only difference between C and C++ in this regards is that in C++, const in the global scope implies static, while in C it doesn't. So C++ "const int = 5;" is equivalent to C and C++ "static const int = 5;", while C "const int = 5" is equivalent to C++ "extern const int = 5;" (which is invalid syntax in standard C, as in C extern can only be used in a declaration and not in a definition). In both C and C++ you would use "extern const int;" to access the non-static constant from a different compilation unit.

File permissions in the kernel

Posted Aug 6, 2016 19:16 UTC (Sat) by xtifr (guest, #143) [Link]

Really? I haven't actually looked that closely.

The difference may be less than you think, though. You can make a pointer to a const int (and this should prevent the compiler from optimizing away the storage), but the same is true of an inline function. The real difference between an inline and a static is that a static will have a separate copy for each translation unit, while an inline will only have one copy for the whole program. (Assuming they aren't all optimized away.)

For normal use (no pointers), the difference won't matter, since the storage will be elided if you turn on even the most basic optimizations (which is pretty normal). And, since you can't modify a const int even with a cast (unless I've just found a bug in g++), the only practical difference would be if you tried to compare two different pointers to what you thought was the same const int. If the const is static, then the comparison *might* fail; if it's inline, it would succeed. But that's not something I've ever done or seen done, so I honestly don't know what the right answer is.

Anyway, I suspect we're drifting a bit off topic, and what you say sounds plausible enough, so I'm certainly not going to contradict you.

File permissions in the kernel

Posted Aug 13, 2016 2:38 UTC (Sat) by thestinger (guest, #91827) [Link]

There are differences. C++ allows a static const to be used in a constant expression, such as defining another static const or using it as a non-variable-length array size.

File permissions in the kernel

Posted Aug 5, 2016 7:11 UTC (Fri) by k8to (guest, #15413) [Link] (1 responses)

In the C model, each code unit (file) is separately compiled into objects, and the system presumes all global symbols are globally visible. When a global const int is compiled into a code unit, memory is set aside for it, and the generated code uses the value by a memory offset.

Theoretically, in another language, the promise that it is const could be strong enough that whole-program optimization could eventually fold away its existence as a memory-located value, but C doesn't give promises that strong for const items.

Placing the definition in a header doesn't help, then you get N definitions of the same-named item, all with global scope. I'm pretty sure this is an error, and in any event if it worked, you'd have the value in memory many times, once for each unit.

Declaring it extern in a header and providing it in one unit gets you one value in memory, but still you don't get the immediates. The meaning of such a symbol is a memory value.

If you declare it as static const int, then a relatively modern compiler will *usually* be able to fully optimize it. You can still break everything by taking the address of it anywhere, which will push it back into memory. Sometimes insufficiently experienced programmers will make this type of mistake, and de-optimize your carefully constructed const int, potentially causing problems later that can be difficult to spot.

The define is very simple to understand, by contrast, which is it's strength.

File permissions in the kernel

Posted Aug 5, 2016 13:32 UTC (Fri) by epa (subscriber, #39769) [Link]

You're right, static const int is what's needed. But just taking the address of it, while it does require allocating four bytes of space for the integer, need not stop other uses of it from being an inlined constant. A quick experiment with gcc -O seems to confirm this.

The arguments for and against use of the preprocessor have often been covered. One common reason to prefer language constructs over macros is that they are easier for static analysis tools. I wonder whether the Sparse tool is able to track uses of a named constant defined with the preprocessor?

File permissions in the kernel

Posted Aug 5, 2016 7:27 UTC (Fri) by mchapman (subscriber, #66589) [Link] (2 responses)

> There are reasons to prefer defines over const vars. A const int with global visibility occupies memory, while a define may not (it may become an operation immediate).

I have frequently seen enum values used for constants instead of preprocessor macros or const variables. They end up in the program's debugging info, so you can use their names in gdb, but they don't require any memory in the process itself.

File permissions in the kernel

Posted Aug 5, 2016 13:55 UTC (Fri) by andresfreund (subscriber, #69562) [Link]

Fwiw, GCC/gdb can do that with macros too. Quite useful. -ggdb seems to do the trick for me.

File permissions in the kernel

Posted Aug 8, 2016 1:39 UTC (Mon) by JdGordy (subscriber, #70103) [Link]

For some reason MISRA (or the subset I'm using at work) forbids #define's so we are stuck using the enum version.

File permissions in the kernel

Posted Aug 5, 2016 13:30 UTC (Fri) by Jonno (subscriber, #49613) [Link]

> A const int with global visibility occupies memory
But a static const int does not (assuming it's initializer is a constexpr, it's address is never taken, and optimizations are turned on or --fno-keep-static-consts is passed to gcc).


Copyright © 2025, Eklektix, Inc.
Comments and public postings are copyrighted by their creators.
Linux is a registered trademark of Linus Torvalds