这周我和同事老诸继续上周的工作,完善项目代码的参数检查和内存释放。每修改完一个项目代码,我们会进行常规场景的简单自测。测试通过,基本说明修改的代码没有问题。测试通不过,review代码,相互检查,及时发现代码遗漏之处。其实测出bug并不可怕,查看log或者dmp文件,在git上对比改动点,很快就能够定位到问题。
然而代码老是通不过某项测试,log没有显示异常,也没有dmp文件。必现的bug呈现在面前,我和老诸只能在代码里增加log,查看过程中的变量值是否异常。按理说这些值不会有异常,因为我们只是修改参数检查和内存释放,基本没有修改算法相关的代码。对比改动点,除了必要的参数检查,没修改过什么。
反复增加了很多log,我和老诸四目相对,除了露出尴尬而不失礼节的笑,都百思不得其解。
一筹莫展之际,老诸突然注意到我们之前忽略的一个改动点,他把某个参数类型从int16_t改为uint_16t,即把原来有符号的16位整型改为无符号的16位整型。这样一来,这个变量只能表示非负数[0, 2^16-1],但算法过程中该值为负数是有意义的。
有符号数和无符号数
以int8_t和uint8_t为例,分别表示有符号的8位整型和无符号的8位整型。
对无符号数uint8_t:
对有符号数int8_t:
有符号数转换为无符号数,会发生什么
C语言允许在各种㓊的数字数据类型之间强制转换,把一个有符号数赋给一个无符号数(或者反过来),结果是各个位不变,但会改变解释这些位的方式。无符号的0x10001011表示139,但有符号的0x10001011表示的-117,这是因为:
上面公式里的B-二进制,2-to,U-无符号数,8-bit位数为8,T-补码
拷问老诸,为什么要去修改?
原因找到了,修改过来后测试通过。我问老诸当时为什么要修改这里呢?老诸说,他使用的是VS2019,如果代码里有类型不严格匹配的地方,那一整行代码下方都会有绿色波浪线提示。绿色波浪线让老诸很不爽,于是就按照提示把int16_t修改成uint16_t……