以下两个代码段之间有什么区别吗?
A:
int x = get_some_int();
uint8_t y = x;
B:
int x = get_some_int();
uint8_t y = (uint8_t) x;
此外,如果y
是函数的uint8_t
自变量并且将x
传递到函数中(有或没有显式强制转换)怎么办?
编辑::请允许我重新表述一个问题:在C中,在分配或传递给其他类型时始终显式转换变量是否是C的优良作法?还是将其留给编译器是一种好习惯?程序员应该做的“默认”是什么?
答案 0 :(得分:1)
问题不是强制转换之一(不需要分配是直接转换为POST http://localhost:9200/myindex/mytype/_bulk
C11 Standard - 6.5.16.1 Simple assignment(p2)),问题是范围之一。 uint8_t
是一个32位带符号整数,能够保存int x;
范围内的值。相反,-2147483648 to 2147483647
是一个无符号的8位值,能够保存值uint8_t y;
。
您可以轻松地为0 - 255
分配一个超出x
范围的值。那会发生什么呢?如果y
的值超出了x
的范围,则y
的值将以模数x
降到1 + max_for_type
C11 Standard - 6.2.5 Types(p9)以内,因此如果y
的值超出了y = x % 256;
的范围,则分配等同于x
。
例如,uint8_t
是x = 25306708;
被x
转换为uint8_t
时,y = x;
的模数为x
,以适应{ {1}}。 (例如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 */
回答:
“始终显式转换变量是否是C的良好做法”
否。如果您正在执行的操作涉及不兼容的类型,则强制转换将屏蔽编译器将生成的警告。您应该只进行很少的转换,并且只应在库API等要求的明确需要的地方进行转换。
仔细检查一下,如果还有其他问题,请告诉我。
答案 1 :(得分:1)
C 2018标准在第6.5.16.1节第2段中指出:
在简单赋值(
=
)中,将右操作数的值转换为赋值表达式的类型,并替换存储在由左操作数指定的对象中的值。
因此,是的,转换是隐式进行的。 C标准不要求您使用强制转换。
但是,仅允许某些操作数。第1段在很大程度上表示,左操作数和右操作数必须都为算术类型或必须具有兼容的类型。 1 因此,如果左操作数和右操作数不满足第1段中的条件,您必须使用强制转换将正确的操作数转换为满足条件的类型。
这给了我们这些情况:
1 第1段的全文为:
应满足以下条件之一:
-左侧的操作数具有原子,合格或不合格的算术类型,右侧的操作数具有算术类型;
-左操作数具有与右类型兼容的结构或联合类型的原子,合格或不合格版本;
-左操作数具有原子,合格或不合格的指针类型,并且(考虑到左操作数在左值转换后将具有的类型)两个操作数都是指向兼容类型的合格或不合格版本的指针,并且类型由左侧具有右侧所指类型的所有限定词;
-左操作数具有原子,限定或不限定的指针类型,并且(考虑到左操作数在左值转换后将具有的类型),一个操作数是指向对象类型的指针,另一个是指向限定类型的指针或
void
的非限定版本,并且左侧指向的类型具有右侧指向的类型的所有限定符;-左操作数是原子,限定或不限定的指针,而右是空指针常量;或
-左边的操作数的类型是原子,限定或不限定的
_Bool
,而右边的是指针。