为什么以下代码会打印出255
?
#include <stdint.h>
#include <stdio.h>
int main(void) {
uint8_t i = 0;
i = (i - 1) % 16;
printf("i: %d\n", i);
return 0;
}
我假设了15
,虽然i - 1
的值为整数。
int
的类型都会转换为int
。通常情况下无法避免这种情况。i
提升为int
。表达式被评估为int
(您使用的常量也是int
)。模数是-1
。然后通过赋值将其转换为uint8_t
:255
。printf
,i
再次被提升为int
:(int)255
。但是,这不会造成任何影响。a < 0
,a % b
不一定是负数。它是实现定义的,可以是15
。但是,自C99以来,-1 % 16
保证为-1
,因为除法必须产生代数商。
unsigned
。i = ((unsigned)i - 1) % 16;
建议:启用编译器警告。至少,赋值转换应该给出截断警告。
a / 16 == -1
)不符合要求。C99解释(第67页上的6.5.5,第164和165页上的7.20.6)也是一个有用的资源。 - cremno((unsigned)i - 1) % 16
保证在0到15的范围内,因此将其分配给uint8_t
不应该有警告,因为该值不会超出范围。 - M.M使用Microsoft C编译器(没有stdint.h,所以我使用了typedef),这段代码可以正常工作(显示15):
#include <stdio.h>
typedef unsigned char uint8_t;
int main(void) {
uint8_t i = 0;
i = (uint8_t)(i - 1) % 16;
printf("i: %d\n", i);
return 0;
}
255是因为(i-1)被提升为整数,在C中用于%的整数除法会向零舍入,而不是向负无穷大舍入(向负无穷大舍入是数学、科学和其他编程语言采用的方式)。因此,在C中,%为零或具有与被除数相同的符号(在本例中,-1%16 == -1),而在数学中,模运算为零或具有与除数相同的符号。
0 - 1
是-1
。MAX_INT
是>= 32767
。 - too honest for this siteuint8_t
)被转换为int
。它可能会被转换为unsigned int
,但仅当int
类型不能覆盖uint8_t
的所有值时才会发生,这是可能的,但非常不太可能发生。 - Grzegorz Szpetkowskiint
至少是16位,而uint8_t
正好是8位,因此实际上是不可能的。 - David Eisenstat