能否将uint64_t与double互转的位转换函数改为宏?因TinyC不优化内联调用
Solution: Bit-Cast Macros for uint64_t ↔ double in TinyC
Since TinyC doesn’t automatically inline function calls the way Clang or GCC do, replacing your bit-cast functions with macros is the perfect workaround—macros expand directly into inline code, eliminating any function call overhead.
The Macros
We’ll use unions for type-punning (this is standard-compliant in C for POD types, unlike raw pointer casts which can trigger strict aliasing issues):
#include <stdint.h> // Required for uint64_t // Convert uint64_t bit pattern to double #define UINT64_TO_DOUBLE(u) ({ \ union { \ uint64_t as_uint64; \ double as_double; \ } _tmp = {.as_uint64 = (u)}; \ _tmp.as_double; \ }) // Convert double bit pattern to uint64_t #define DOUBLE_TO_UINT64(d) ({ \ union { \ double as_double; \ uint64_t as_uint64; \ } _tmp = {.as_double = (d)}; \ _tmp.as_uint64; \ })
How It Works
- The GNU-style statement expression
({ ... })lets the macro behave like a function—it can be used anywhere an expression is allowed (e.g., assigning to a variable, passing as a function argument). - The union ensures we’re reinterpreting the exact same memory bytes as a different type, no conversion or bit manipulation happens—this is true bit-casting.
- Wrapping the parameters
(u)and(d)in parentheses prevents macro expansion bugs caused by operator precedence (e.g., if you pass an expression likex | yinstead of a single variable).
Usage Example
#include <stdio.h> int main() { // Test uint64_t → double uint64_t pi_bits = 0x400921FB54442D18; // Bit pattern for π (3.141592653589793) double pi = UINT64_TO_DOUBLE(pi_bits); printf("uint64_t 0x%lx → double: %.15f\n", pi_bits, pi); // Test double → uint64_t double e = 2.718281828459045; uint64_t e_bits = DOUBLE_TO_UINT64(e); printf("double %.15f → uint64_t: 0x%lx\n", e, e_bits); return 0; }
Key Notes
- Make sure to include
<stdint.h>to get theuint64_ttype definition. - The temporary union variable (
_tmp) uses an underscore prefix to minimize the chance of name collisions with your code. - If TinyC doesn’t support GNU statement expressions (unlikely, but possible), you can rewrite the macros using block scopes for standalone statement use:
Then use it like:#define UINT64_TO_DOUBLE(u, out) do { \ union { uint64_t as_uint64; double as_double; } _tmp; \ _tmp.as_uint64 = (u); \ (out) = _tmp.as_double; \ } while(0)UINT64_TO_DOUBLE(pi_bits, pi);
内容的提问来源于stack exchange,提问作者exebook
相关产品推荐
相关产品推荐

