按位运算会导致意外的变量大小

问题描述 投票:1回答:1

Context

我们正在移植最初使用PIC微控制器使用8位C编译器编译的C代码。为了防止无符号全局变量(例如,错误计数器)回滚到零,使用了一个常见的习惯用法,如下所示:

if(~counter) counter++;

这里的按位运算符将所有位取反,并且仅当counter小于最大值时,该语句为true。重要的是,无论变量大小如何,此方法均有效。

问题

我们现在瞄准使用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

在输出的第一行中,我们得到了预期的结果:i是1个字节。但是,i的按位补码实际上是[四个字节] >>,这引起了一个问题,因为现在与之比较将无法给出预期的结果。例如,如果这样做(其中i是正确初始化的uint8_t):

if(~i) i++;

我们将看到i从0xFF回绕到0x00。与以前按照以前的编译器和8位PIC微控制器的预期工作时相比,GCC中的这种行为有所不同。

我们知道我们可以通过如下方式解决此问题:

if((uint8_t)~i) i++;

或,通过

if(i < 0xFF) i++;

但是,在这两种解决方法中,变量的大小必须已知,并且对于软件开发人员来说容易出错。这些上限检查在整个代码库中进行。有多种大小的变量(例如uint16_tunsigned char等),我们不希望在其他可以正常运行的代码库中更改它们。

问题

我们对问题的理解是否正确,是否有解决此问题的选项,而无需重新访问使用这种习语的每种情况?我们的假设正确吗,像按位补码之类的操作应返回与操作数相同大小的结果?似乎这将中断,具体取决于处理器体系结构。我觉得自己正在服用疯狂药丸,而C应该比这更便携。同样,我们对此的理解可能是错误的。

从表面上看,这似乎不是一个大问题,但是这种先前使用的习惯用法已在数百个地方使用,我们希望在进行昂贵的更改之前先了解这一点。


注意:

这里有一个看似相似但不完全相同的问题:Bitwise operation on char gives 32 bit result

我没有看到这里讨论的问题的真正症结,即按位补码的结果大小与传递给运算符的结果大小不同。

上下文我们正在移植最初使用PIC微控制器使用8位C编译器编译的C代码。为了防止未签名的全局变量而使用的通用用法(对于...

c microcontroller bitwise-operators sizeof
1个回答
0
投票

sizeof(i);

© www.soinside.com 2019 - 2024. All rights reserved.