1

Is there a way to check at compile time if the argument of a macro is an integer literal, and evaluate the macro differently in that case?

#include <stdio.h> #define VALUE_0 0 #define VALUE_1 2 #define VALUE_2 4 #define VALUE_3 6 #define VALUE_4 8 #define VALUE(_idx_) VALUE_ ## _idx_ #define VALUE_(_idx_) 2*(_idx_) int main() { printf("%i\n", VALUE(3)); printf("%i\n", VALUE_(1+2)); } 

VALUE(3) is always resolved at compile-time, but only works if 3 is an integer literal. VALUE_(3) works for any argument type, but may be result in an expression that is computed at runtime (in a more complex case), and make compiler optimizations impossible.

If there a way to write the macro such that is automatically resolves to VALUE_ or to VALUE, depending if the argument is an integer literal.

Edit:

It is for a C program, or more specifically OpenCL C. It seems that for some OpenCL C compilers (for example NVidia nvcc and Intel), an expression like VALUE(idx) does not always get resolved at compile time, even when the argument is a constant. (Or at least the kernel does not get auto-vectorized if it contains such an expression.) For example if VALUE() resolves to a call of an inline function containing a switch statement, or to a lookup of a constant array, it does not work, but if it is an nested ?: expression, it works. VALUE_ would be guaranteed to resolve to a constant.

Because I'm generating C source code at runtime from the host and passing it to the OpenCL C compiler, it would be useful to not have to generate two different macros for each array.

12
  • 7
    C or C++? Pick one. It matters. Commented Mar 12, 2018 at 14:12
  • I feel like even if it is possible it could lead to a lot of confusion. How would it handle something that's const or constexpr? Just because it's not a literal doesn't mean it isn't computed at compile time. Even in your example any sane compiler would compute 1+2 at compile time. Commented Mar 12, 2018 at 14:14
  • 2
    @nwp: Yes, to emphasise, nobody is being pedantic here. It matters a lot in this particular case. C and C++ have diverged on their handling of this. Commented Mar 12, 2018 at 14:14
  • Are you sure that VALUE_(3) is not already resolved at compile time? Converting 2*(3) to 6 is fairly easy optimization for the compiler. Commented Mar 12, 2018 at 14:17
  • @Bathsheba I. e. they've been using different pre-processors since <whenever>??? Commented Mar 12, 2018 at 14:24

2 Answers 2

1

I'd recommend always using the latter:

#define VALUE_(_idx_) 2*(_idx_) 

If the argument is a constant or a constant expression, the resulting expression after the preprocessor will be evaluated by the compiler. If it is not, it will be evaluated at runtime.

The only difference between the two macros in the case of an integer literal is whether the preprocessor gives you the final result or whether the compiler does. In both cases, there is no runtime overhead, so better to go with the one that gives you the most flexibility.

Sign up to request clarification or add additional context in comments.

1 Comment

I agree, though there's room to suppose that the 'real' context is not quite as simple as in the question.
0

I'll turn the problem on its head and suggest that you try forcing the compiler to compute the value (with the additional benefit of asserting that the value is, in fact, a compile-time constant):

#define MAKE_ME_CONSTANT(x) sizeof((struct{char c[x];}){{0}}.c) 

This (tweaked from an earlier answer of mine) declares an anonymous structure with a char-array member whose size is your constant. It then instantiates it with a compound literal and retrieves the member's size. All of this is part of the unevaluated operand of a sizeof, so I expect any compiler to make it a constant.

Note: I didn't use the simpler sizeof(char[x]) because that could be a VLA. But VLAs can't be structure members, so we're good here.

Hence, you get:

#define VALUE(_idx_) MAKE_ME_CONSTANT(2*(_idx_)) 

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.