OSX Darwin中memcmp(3)手册描述与实际测试结果不符的疑问
你的问题确实有点反直觉——明明man手册明确说明memcmp会把字节当作无符号char处理,\200(对应十六进制0x80)应该比\0大,返回正数,但实际运行代码却输出了-1。这里的关键原因和clang的内置优化、memcmp的具体实现细节有关:
C标准的模糊性:首先要明确,C标准只要求memcmp返回值的符号符合无符号字节比较的结果(小于返回负数、等于返回0、大于返回正数),但并没有强制要求返回值必须是两个字节的精确差值。Apple的man手册里提到的“返回差值”是该平台实现的特定行为,并非标准强制要求。
clang内置memcmp的特殊行为:当你用默认clang编译代码时(尤其是开启优化选项如
-O1及以上时),clang会用内置的__builtin_memcmp代替系统libc中的memcmp实现。这个内置函数不会返回精确的字节差值,而是直接返回-1、0或1来表示比较结果。更关键的是,在你使用的LLVM 9.0.0版本中,这个内置函数可能错误地按有符号char来处理字节:\200作为有符号char是-128,数值上比\0小,所以返回-1。验证方法:你可以尝试编译代码时加上
-fno-builtin-memcmp选项,强制使用系统libc的memcmp实现:clang -fno-builtin-memcmp test.c -o test ./test这时候输出应该会变成
128,和man手册的描述完全一致。
最后再提一句man手册里的重要提示:可移植代码应该只依赖返回值的符号,而不是具体数值。无论memcmp返回的是128还是1,只要是正数就表示第一个字符串大于第二个;返回负数则表示小于,这样写出来的代码才能在不同平台上稳定运行。
内容的提问来源于stack exchange,提问作者1ShotSniper

