Say I have a scenario where I need to ensure that a value used in my code is a compile-time constant (e.g. perhaps a draconian interpretation of P10 rule 2 "fixed loop bounds"). How can I enforce this at the language-level in C?
C supports the notion of integer constant expression at the language-level. It must be possible to work out a way to take advantage of this so that only values complying with this specification can be used in expressions, right? e.g.:
for (int i = 0; i < assert_constant(10); ++i) {...
Some partial solutions that aren't really general enough to be useful in multiple situations:
- Bitfields: a classic strategy for implementing - static_assertin C prior to C11 was to use a bitfield whose value would be illegal when a condition failed:- struct { int _:(expression); }- While this could be easily wrapped for use as part of an expression, it isn't general at all - the maximum value of - expression"[may] not exceed the width of an object of the type that would be specified were the colon and expression omitted" (C11 6.7.2.1), which places a very low portable limit on the magnitude of- expression(generally likely to be 64). It also may not be negative.
- Enumerations: an - enumdemands that any initializing expressions be integer constant expressions. However, an- enumdeclaration cannot be embedded into an expression (unlike a- structdefinition), requiring its own statement. Since the identifiers in the enumerator list are added to the surrounding scope, we also need a new name each time.- __COUNTER__isn't standardized, so there's no way to achieve this from within a macro.
- Case: again, the argument expression to a - caseline must be an integer constant. But this requires a surrounding- switchstatement. This isn't a whole lot better than- enum, and it's the kind of thing you don't want to hide inside a macro (since it will generate real statements, even if they're easy for the optimizer to remove).
- Array declaration: since C99, the array size doesn't even have to be a constant, meaning it won't generate the desired error anyway. It also again is a statement that requires introducing a name into the surrounding scope, suffering from the same problems as - enum.
Surely there's some way to hide the constant check in a macro that's repeatable, passes the value through (so it can be used as an expression), and doesn't require a statement line or introduce extra identifiers?
 
    