You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

能否将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 like x | y instead 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 the uint64_t type 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:
    #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)
    
    Then use it like: UINT64_TO_DOUBLE(pi_bits, pi);

内容的提问来源于stack exchange,提问作者exebook

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.19 07:36:14