浅谈 inline

基于开源文章的个人纠错,原文链接

先给两句掷地有声的结论:

小小纠偏 & 关键补充


纠正文中示例(更安全的写法)

#include <stdio.h>

static inline const char* odd_even(int x) {
    return (x & 1) ? "奇" : "偶";
}

int main(void) {
    for (int i = 1; i < 100; ++i) {
        printf("i:%d    奇偶性:%s\n", i, odd_even(i));
    }
}

要点:


A. 驱动/嵌入式里的高频小刀(可放心内联)

1) 寄存器读写封装(MMIO)

// mmio.h
#include <stdint.h>
static inline void  mmio_write32(volatile uint32_t* base, uint32_t off, uint32_t v){ *(volatile uint32_t*)((uintptr_t)base + off) = v; }
static inline uint32_t mmio_read32 (volatile uint32_t* base, uint32_t off){ return *(volatile uint32_t*)((uintptr_t)base + off); }
static inline void  mmio_set_bits(volatile uint32_t* base, uint32_t off, uint32_t mask){ mmio_write32(base, off, mmio_read32(base, off) | mask); }
static inline void  mmio_clr_bits(volatile uint32_t* base, uint32_t off, uint32_t mask){ mmio_write32(base, off, mmio_read32(base, off) & ~mask); }

热路径上避免函数跳转,还能让编译器把读值短暂寄存优化。

2) 环形队列下标回绕

static inline uint32_t wrap_inc(uint32_t i, uint32_t n){ ++i; return (i == n) ? 0u : i; }

网络驱动、DMA ring 常用;调用点多、逻辑短,典型内联受益者。

3) 位操作小助手

static inline int bit_test(uint32_t v, unsigned b){ return (v >> b) & 1u; }
static inline uint32_t bit_set(uint32_t v, unsigned b){ return v | (1u << b); }
static inline uint32_t bit_clr(uint32_t v, unsigned b){ return v & ~(1u << b); }

4) 简易延时/忙等(需小心)

static inline void cpu_relax(void){ __asm__ __volatile__("" ::: "memory"); } // 或平台指令

自旋锁/等待时配合使用,内联避免调用开销与指令重排。

5) 端序转换(若平台无内建)

static inline uint32_t bswap32(uint32_t x){
    return (x<<24) | ((x<<8)&0x00FF0000u) | ((x>>8)&0x0000FF00u) | (x>>24);
}

B. 数值计算/HPC 里的小而美内联

6) 小型向量算子(SIMD 前的小封装)

struct Vec3 { float x,y,z; };

inline Vec3 fma(const Vec3& a, float s, const Vec3& b){
    return { a.x*s + b.x, a.y*s + b.y, a.z*s + b.z };
}

被内联后,编译器更容易做寄存器分配与常量折叠。

7) 分段函数/快速 clamp

inline float clamp(float v, float lo, float hi){
    return v < lo ? lo : (v > hi ? hi : v);
}

8) 轻量代价函数(近似)

inline float fast_sigmoid(float x){
    return x / (1.0f + fabsf(x));  // 近似 σ(x),热路径中代替真 sigmoid
}

9) 轻量哈希组合(容器键)

inline std::size_t hash_combine(std::size_t a, std::size_t b){
    a ^= b + 0x9e3779b97f4a7c15ull + (a<<6) + (a>>2);
    return a;
}

10) 稀疏矩阵下标计算

inline int csr_row_end(const int* rowptr, int r){ return rowptr[r+1]; }

模板/小函数放头文件,调用点分布广,内联能省很多跳转。


C. 后端/通用库中的实用内联

11) 轻量字符串判定

inline bool starts_with(const std::string& s, const char* p){
    auto n = std::char_traits<char>::length(p);
    return s.size() >= n && std::equal(p, p+n, s.data());
}

12) 轻量 ID/时间戳打包解包

inline uint64_t pack_u32u32(uint32_t hi, uint32_t lo){ return (uint64_t(hi)<<32) | lo; }
inline uint32_t hi32(uint64_t v){ return uint32_t(v >> 32); }
inline uint32_t lo32(uint64_t v){ return uint32_t(v & 0xffffffffu); }

13) 简单范围检查

template<typename T>
inline bool in_range(T v, T lo, T hi){ return (v >= lo) & (v < hi); } // 可选用按位与避免分支

14) 轻量错误码包装(无 I/O)

inline const char* errstr(int ec){
    switch(ec){
        case 0:  return "OK";
        case 1:  return "E_IO";
        case 2:  return "E_TIMEOUT";
        default: return "E_UNKNOWN";
    }
}

15) 小型 RAII 辅助(头文件类内定义天然内联)

struct ScopeGuard {
    void (*f)();
    ~ScopeGuard(){ if(f) f(); }
};

这些场景急着内联


工具链与策略建议


头文件组织的一个落地范式(C 风格)

// util_bits.h
#ifndef UTIL_BITS_H
#define UTIL_BITS_H
#include <stdint.h>

static inline int bit_test(uint32_t v, unsigned b){ return (v >> b) & 1u; }
static inline uint32_t bit_set(uint32_t v, unsigned b){ return v | (1u << b); }
static inline uint32_t bit_clr(uint32_t v, unsigned b){ return v & ~(1u << b); }

#endif // UTIL_BITS_H

一页小抄:使用决策树