起源是给网友讲 qsort 里那个诡异的 cmp

讲完后让对面写了一篇。这里补充一些细节。

qsort

泛型简单介绍

就是对不同的 type 复用代码。

c 里面如何实现泛型

用无类型指针 (void *),类比 as any

为什么要 sizeof item

引出指针丢失信息。c 本身缺乏泛型,用 void * 模拟 any,但是这样会丢失信息,只能再传一个 sizeof 来补全丢失的信息。函数内部也需要再转回 (int *) 再 * 来补充信息。

函数指针对应 label 跳转

打开 godbolt

Compiler Explorer - C (x86-64 gcc 12.1)

参数 -S 表示不优化

compare:
  push rbp
  mov rbp, rsp
  mov QWORD PTR [rbp-8], rdi
  mov QWORD PTR [rbp-16], rsi
  mov rax, QWORD PTR [rbp-8]
  mov edx, DWORD PTR [rax]
  mov rax, QWORD PTR [rbp-16]
  mov eax, DWORD PTR [rax]
  sub edx, eax
  mov eax, edx
  pop rbp
  ret
main:
  push rbp
  mov rbp, rsp
  sub rsp, 32
  mov DWORD PTR [rbp-32], 12
  mov DWORD PTR [rbp-28], 8
  mov DWORD PTR [rbp-24], 4
  mov DWORD PTR [rbp-20], 23
  mov DWORD PTR [rbp-16], 5
  lea rax, [rbp-32]
  add rax, 4
  mov ecx, OFFSET FLAT:compare ;; here
  mov edx, 4
  mov esi, 3
  mov rdi, rax
  call qsort ;; here
  mov eax, 0
  leave
  ret

指针指的地址对应 label, 传入 ecx 寄存器,然后 call 调用。