下面两段代码有什么区别吗?
答:
int x = get_some_int();
uint8_t y = x;
乙:
int x = get_some_int();
uint8_t y = (uint8_t) x;
另外,如果
y
是函数的uint8_t
参数,并且x
被传递到函数中(有或没有显式强制转换),会怎么样?编辑:请允许我重新表述一个问题:在分配或传递给其他类型时,在C中总是显式地转换变量是一个好的做法吗?或者把这个留给编译器是好的做法吗?程序员应该“默认”做什么?
最佳答案
问题不是强制转换(不需要赋值是直接转换到uint8_t
C11 Standard - 6.5.16.1 Simple assignment(p2)),而是范围问题。int x;
是一个32位有符号整数,能够保存-2147483648 to 2147483647
范围内的值。相反,uint8_t y;
是一个无符号的8位值,能够保存值0 - 255
。
您可以很容易地为x
指定一个超出y
范围的值。那么接下来会发生什么呢?如果x
的值超过y
的范围,则x
的值将被减模1 + max_for_type
以适合y
C11 Standard - 6.2.5 Types(p9)的范围,因此对于超过y = x % 256;
的x
的值,赋值等价于uint8_t
。
例如x = 25306708;
然后当x
转换为uint8_t
时,将y = x;
x
的模256
减小为适合y
的模。(例如y == 84
)
如果您想避免值的无声减少以适应y
,那么由您来测试x
的值是否适合y
,而不会减少。您可以使用一个简单的条件和stdint.h
中定义的常量来实现这一点,例如。
y = x; /* direct assignment, no cast required */
if (0 <= x && x <= UINT8_MAX) /* validate x within the range of uint8_t */
printf ("int x: %d is in range of uint8_t y: %" PRIu8 "\n", x, y);
else
/* handle the error as required */
举一个简短的例子来说明这种行为,你可以做到:
#include <stdio.h>
#include <inttypes.h> /* includes stdint.h */
int main (void) {
int x;
uint8_t y;
fputs ("enter a value: ", stdout);
if (scanf ("%d", &x) != 1) {
fputs ("error: invalid integer value.\n", stderr);
return 1;
}
y = x; /* direct assignment, no cast required */
if (0 <= x && x <= UINT8_MAX) /* validate x within the range of uint8_t */
printf ("int x: %d is in range of uint8_t y: %" PRIu8 "\n", x, y);
else
printf ("x: %d exceeds range of uint8_t, reduced modulo to y: %"
PRIu8 "\n", x, y);
}
示例使用/输出
$ ./bin/intuint8_t
enter a value: 254
int x: 254 is in range of uint8_t y: 254
$ ./bin/intuint8_t
.enter a value: 256
x: 256 exceeds range of uint8_t, reduced modulo to y: 0
$ ./bin/intuint8_t
enter a value: 25306708
x: 25306708 exceeds range of uint8_t, reduced modulo to y: 84
回答:
“在C语言中,总是显式地转换变量是一种好的做法吗?”
不。如果您所做的操作涉及不兼容的类型,强制转换将屏蔽编译器将生成的警告。您应该只在库API等明确需要的地方进行很少的强制转换。。
再看一遍,如果你还有问题,请告诉我。
关于c - 是C赋值和参数传递导致隐式转换,还是应该显式转换?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/55768679/