TE
TechEcho
Home24h TopNewestBestAskShowJobs
GitHubTwitter
Home

TechEcho

A tech news platform built with Next.js, providing global tech news and discussions.

GitHubTwitter

Home

HomeNewestBestAskShowJobs

Resources

HackerNews APIOriginal HackerNewsNext.js

© 2025 TechEcho. All rights reserved.

Detecting if an expression is constant in C

44 pointsby signa115 days ago

4 comments

sleirsgoevy1 day ago
The Linux kernel has even a way to determine whether the expression is compile-time, WITHOUT aborting compilation in either case.<p>The trick is this (copied vebratim from Linux):<p>#define __is_constexpr(x) (sizeof(int) == sizeof(*(8 ? ((void *)((long)(x) * 0l)) : (int *)8)))<p>Explanation: if x is a constant expression, then multiplying it by zero yields a constant 0, and casting a constant 0 to void* makes a null pointer constant. And the ternary expression, if one of its sides is a null pointer constant, collapses to the type of the other side (thus the type of the returned pointer will be int*, and the sizeof will match). And if x was not constant, then the lefthand side would not be considered a null pointer constant by type inference, the type of the ternary expression will be void*, and the sizeof check will not match.<p>With a few more clever tricks, it&#x27;s even possible to implement a compile-time &quot;type ternary expression&quot;, like this: TYPE_IF(2 * 2 == 4, int, long). This is left as an exercise for the reader.
评论 #43977707 未加载
评论 #43975503 未加载
wahern1 day ago
&gt; This works. But both gcc and clang warn about the enum being anonymous... even though that&#x27;s exactly what I wanted to do. And this cannot be silenced with #pragma since it&#x27;s a macro, so the warning occurs at the location where the macro is invoked.<p>You can use _Pragma instead of #pragma. E.g.<p><pre><code> #define C(x) ( \ _Pragma(&quot;clang diagnostic push&quot;) \ _Pragma(&quot;clang diagnostic ignored \&quot;-Wvisibility\&quot;&quot;) \ (x) + 0*sizeof(void (*)(enum { tmp = (int)(x) })) \ _Pragma(&quot;clang diagnostic pop&quot;) \ ) </code></pre> EDIT: Alas, GCC is a little pickier about where _Pragma is allowed so you may need to use a statement expression. Also, it seems GCC 14 doesn&#x27;t have a -W switch that will disable the anonymous enum warning.
bobbyi1 day ago
I thought this would work:<p>#define C(x) (sizeof(char[x]), x)<p>sizeof is a compile-time operation so x need to be known at compile time.<p>It didn&#x27;t work as expected. It turns out there is an exception and the standard says that sizeof is actually calculated at runtime specifically for variable length arrays:<p>&gt; The sizeof operator yields the size (in bytes) of its operand, which may be an expression or the parenthesized name of a type. The size is determined from the type of the operand. The result is an integer. If the type of the operand is a variable length array type, the operand is evaluated; otherwise, the operand is not evaluated and the result is an integer constant.
pjc501 day ago
It&#x27;s remarkable that people will say that doing this kind of thing is better than learning a language which actually lets you enforce this with the type system.<p>(or even just insist that users use the version of the language which supports &quot;constexpr&quot;!)
评论 #43974678 未加载
评论 #43976198 未加载
评论 #43974510 未加载
评论 #43974696 未加载
评论 #43975126 未加载
评论 #43977343 未加载