C 语言的奇技淫巧:高级技巧与黑科技

C 语言作为一门接近硬件的编程语言,以其灵活性和强大的底层控制能力著称。在长期的实践中,开发者们总结了许多“奇技淫巧”(高级技巧或非传统用法),这些技巧可以帮助我们写出更高效的代码,但也可能牺牲可读性和可移植性。本文将介绍一些常见的 C 语言技巧,并附上代码示例,供大家参考和学习。


1. 预处理宏的魔法

1.1 代码生成

通过宏可以生成重复的代码,减少手动编写的工作量

#define DEFINE_FUNC(type) \
    type add_##type(type a, type b) { return a + b; }

DEFINE_FUNC(int)    // 生成 int add_int(int a, int b) { ... }
DEFINE_FUNC(float) // 生成 float add_float(float a, float b) { ... }

1.2 编译时断言

利用宏在编译时进行断言检查

#define STATIC_ASSERT(cond) typedef char static_assert[(cond) ? 1 : -1]
STATIC_ASSERT(sizeof(int) == 4); // 如果 int 不是 4 字节,编译失败

2. 位操作黑科技

2.1 快速乘除

通过位操作实现快速的乘除法

int a = b << 3;    // 等价于 b * 8
int c = d >> 2;    // 等价于 d / 4(仅适用于正数)

2.2 交换变量

使用异或操作交换两个变量的值,无需临时变量

a ^= b; b ^= a; a ^= b; // 异或交换(但可读性差,且对浮点数无效)

2.3 判断奇偶性

通过位操作快速判断一个数的奇偶性

if (n & 1) { /* 奇数 */ }

3. 指针的骚操作

3.1 偏移指针访问结构体

通过指针偏移访问结构体成员

struct Data { int x; double y; };
struct Data d;
double *py = &d.x + 1; // 假设内存对齐允许(可能未定义行为!)

3.2 通过空指针访问成员

计算结构体成员的偏移量

#define offsetof(type, member) ((size_t)&((type *)0)->member)
// 计算结构体成员的偏移量(标准库已实现,但原理如此)

4. 结构体内存布局控制

4.1 位域节省内存

使用位域来节省内存空间

struct Buffer {
    size_t length;
    char data[]; // C99 柔性数组,用于动态分配内存
};
struct Buffer *buf = malloc(sizeof(struct Buffer) + 100);

5. 利用未定义行为(慎用!)

5.1 类型双关(Type Punning)

直接读取浮点数的二进制表示

float f = 1.0;
int i = *(int *)&f; // 直接读取 float 的二进制表示(需注意字节序)

5.2 通过指针修改常量

通过指针修改常量的值(不可靠)

const int x = 42;
int *p = (int *)&x;
*p = 100; // 未定义行为!某些平台会崩溃

6. 内联汇编优化

在关键代码中嵌入汇编以提升性能(平台相关)

int add(int a, int b) {
    __asm__("addl %%ebx, %%eax;" : "=a"(a) : "a"(a), "b"(b));
    return a;
}

7. 函数指针的妙用

7.1 动态分发

通过函数指针实现动态分发

void (*func_ptr)(int) = NULL;
func_ptr = &my_function;
func_ptr(42); // 调用函数

7.2 模拟面向对象

使用函数指针模拟面向对象编程

typedef struct {
    void (*print)(void *self);
} Object;

void String_print(void *self) { printf("%s\n", (char *)self); }
Object str_obj = { .print = String_print };
str_obj.print("Hello");

8. 代码优化技巧

8.1 循环展开

通过循环展开减少循环开销

for (int i = 0; i < 100; i += 4) {
    process(i); process(i+1); process(i+2); process(i+3);
}

8.2 查表法代替计算

使用查表法代替复杂的计算

static const int sin_table[360] = {0, ...};
int sin_value = sin_table[angle % 360];

9. 利用编译器扩展

9.1 分支预测提示(GCC)

通过编译器扩展提示分支预测

if (__builtin_expect(condition, 0)) { // 提示编译器 condition 可能为假
    // 处理冷门分支
}

9.2 编译时计算(C11 constexpr

在编译时进行计算

constexpr int factorial(int n) { return (n <= 1) ? 1 : n * factorial(n-1); }

10. 非常规代码生成

10.1 自修改代码

生成自修改代码(需关闭内存保护)

void (*func)() = (void (*)()) malloc(100);
// 向 func 指向的内存写入机器码(高度平台相关,现代系统通常禁止)

注意事项

  1. 可读性 vs 性能:多数技巧会降低代码可读性,仅在必要时使用(如嵌入式系统或性能关键代码)。

  2. 未定义行为:部分技巧依赖编译器或平台(如内存对齐、字节序),需谨慎验证。

  3. 现代替代方案:C11/C17 标准已引入更安全的特性(如 static_assert),优先使用标准方法。


结语

C 语言的这些“奇技淫巧”展示了其强大的底层控制能力,但在实际项目中应权衡利弊,优先保证代码的健壮性和可维护性

📦 硬核资料赠送

>>搓这里关键字>>「C++王者」获取:

1. 《C++后端开发高频八股文》(涵盖23个核心考点)

2. 《C/C++工程师能力自测清单》(50+项技能树Checklist)

3. 【开源项目】libevent-master

4. 【开源项目】workflow-master

5. 《LeetCode 101算法精讲》(剑指Offer最优解合集)

1. C 语言中的指针和内存泄漏 ............................................................................................................. 5 2. C语言难点分析整理 .......................................................................................................................... 9 3. C语言难点 ........................................................................................................................................ 16 4. C/C++实现冒泡排序算法 ................................................................................................................. 29 5. C++中指针和引用的区别 ................................................................................................................. 31 6. const char*, char const*, char*const的区别 ..................................................................................... 32 7. C中可变参数函数实现 .................................................................................................................... 34 8. C程序内存中组成部分 .................................................................................................................... 37 9. C编程拾粹 ........................................................................................................................................ 38 10. C语言中实现数组的动态增长 .................................................................................................... 40 11. C语言中的位运算 ........................................................................................................................ 41 12. 浮点数的存储格式: .................................................................................................................... 45 13. 位域 ................................................................................................................................................ 52 14. C语言函数二维数组传递方法 .................................................................................................... 58 15. C语言复杂表达式的执行步骤 .................................................................................................... 60 16. C语言字符串函数大全 ................................................................................................................ 62 17. C语言宏定义技巧 ........................................................................................................................ 80 18. C语言实现动态数组 .................................................................................................................... 89 19. C语言笔试-运算符和表达式 ....................................................................................................... 93 20. C语言编程准则之稳定篇 ............................................................................................................ 96 21. C语言编程常见问题分析 ............................................................................................................ 97 22. C语言编程易犯毛病集合 .......................................................................................................... 101 23. C语言缺陷陷阱(笔记) ............................................................................................................ 107 24. C语言防止缓冲区溢出方法 .......................................................................................................113 25. C语言高效编程秘籍 ...................................................................................................................115 26. C运算符优先级口诀 ...................................................................................................................119 27. do/while(0)的妙用 ....................................................................................................................... 120 28. exit()和return()的区别 ................................................................................................................ 125 29. exit子程序终止函数return的差别 ........................................................................................ 126 30. externstatic存储空间矛盾 ..................................................................................................... 130 31. PC-LintC\C++代码质量 ........................................................................................................ 132 32. spirntf函数使用大全................................................................................................................... 142 33. 二叉树的数据结构 ...................................................................................................................... 150 34. 位运算应用口诀和实例 .............................................................................................................. 153 35. 内存对齐ANSI C中struct内存布局 .................................................................................... 156 36. 冒泡和选择排序实现 .................................................................................................................. 162 37. 函数指针数组返回数组指针的函数 ...................................................................................... 168 38. 右左法则- 复杂指针解析 ........................................................................................................... 170 39. 回车和换行的区别 ...................................................................................................................... 173 40. 堆和堆栈的区别 .......................................................................................................................... 175 41. 堆和堆栈的区别 .......................................................................................................................... 178 42. 如何写出专业的C头文件 ......................................................................................................... 181 43. 打造最快的Hash表 .................................................................................................................... 185 44. 指针数组学习笔记 .................................................................................................................. 199 45. 数组不是指针 .............................................................................................................................. 201 46. 标准C中字符串分割的方法 ..................................................................................................... 205 47. 汉诺塔源码 .................................................................................................................................. 208 48. 洗牌算法 .......................................................................................................................................211 49. 深入理解C语言指针的奥秘 ..................................................................................................... 213 50. 游戏外挂的编写原理 .................................................................................................................. 229 51. 程序实例分析-为什么会陷入死循环 ......................................................................................... 232 52. 空指针究竟指向了内存的哪个地方 .......................................................................................... 234 53. 算术表达式的计算 ...................................................................................................................... 238 54. 结构体对齐的具体含义 .............................................................................................................. 242 55. 连连看AI算法 ............................................................................................................................ 246 56. 连连看寻路算法的思路 .............................................................................................................. 254 57. 重新认识:指向函数的指针 ......................................................................................................... 258 58. 链表的源码 .................................................................................................................................. 261 59. 高质量的子程序 .......................................................................................................................... 264 60. 高级C语言程序员测试必过的十六道最佳题目+答案详解.................................................... 266 61. C语言常见错误 .......................................................................................................................... 286 62. 超强的指针学习笔记 .................................................................................................................. 291 63. 程序员之路──关于代码风格 .................................................................................................. 306 64. 指针、结构体、联合体的安全规范 .......................................................................................... 309 65. C指针讲解 .................................................................................................................................. 314 66. 关于指向指针的指针 .................................................................................................................. 327 67. C/C++ 误区一:void main() ...................................................................................................... 331 68. C/C++ 误区二:fflush(stdin) ..................................................................................................... 334 69. C/C++ 误区三:强制转换 malloc() 的返回值 ........................................................................ 338 70. C/C++ 误区四:char c = getchar(); ............................................................................................ 339 71. C/C++ 误区五:检查 new 的返回值....................................................................................... 341 72. C 是 C++ 的子集吗? .............................................................................................................. 342 73. C和C++的区别是什么? .......................................................................................................... 345 74. 无条件循环 .................................................................................................................................. 346 75. 产生随机数的方法 ...................................................................................................................... 347 76. 顺序表及其操作 .......................................................................................................................... 348 77. 单链表的实现及其操作 .............................................................................................................. 349 78. 双向链表 ...................................................................................................................................... 353 79. 程序员数据结构笔记 .................................................................................................................. 357 80. Hashtable和HashMap的区别.................................................................................................... 364 81. hash 表学习笔记 ......................................................................................................................... 366 82. C程序设计常用算法源代码 ...................................................................................................... 368 83. C语言有头结点链表的经典实现 .............................................................................................. 375 84. C语言惠通面试题 ...................................................................................................................... 383 85. C语言常用宏定义 ...................................................................................................................... 402
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

C语言小火车

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值