按位运算会导致意外的可变大小
语境 我们正在移植最初使用PIC单片机的8位C编译器编译的C代码。为了防止无符号全局变量(例如,错误计数器)回滚到零,使用了一个常见的习惯用法: if(~counter) counter++; 此处的按位运算符将所有位取反,并且仅当counter小于最大值时该语句才为真。重要的是,无论变量大小如何,此方法均有效。 问题 我们现在的目标是使用GCC的32位ARM处理器。我们注意到,相同的代码会产生不同的结果。据我们所知,按位补码运算返回的值与我们期望的大小不同。为了重现这一点,我们在GCC中进行编译: uint8_t i = 0; int sz; sz = sizeof(i); printf("Size of variable: %d\n", sz); // Size of variable: 1 sz = sizeof(~i); printf("Size of result: %d\n", sz); // Size of result: 4 在输出的第一行中,我们得到的是:i1个字节。但是,的按位补码i实际上是四个字节,这会引起问题,因为与此进行比较现在无法给出预期的结果。例如,如果这样做(在哪里i是正确初始化的uint8_t): if(~i) i++; 我们将看到i从0xFF到0x00的“环绕”。与以前的编译器和8位PIC微控制器中预期的运行方式相比,GCC的行为有所不同。 我们知道我们可以通过如下方式解决此问题: if((uint8_t)~i) i++; 或者,通过 if(i < 0xFF) …