如果我在三元运算符条件中仅使用unsigned
类型,这些unsigned
变量会自动转换为signed
类型吗?
简单示例:
unsigned int prevTickSeconds = 48;
unsigned int currentTickSeconds = 5;
unsigned int secondsLeft = (currentTickSeconds - prevTickSeconds ) ?
currentTickSeconds - prevTickSeconds :
60 - prevTickSeconds + currentTickSeconds;
如本示例所示,(currentTickSeconds > prevTickSeconds)
时此构造是否正常工作?是否会为三元运算符中的条件自动执行类型转换?
答案 0 :(得分:5)
不,没有这样的转换,因为所有类型都是unsigned int
并且会出现“下溢”。
注:
60 - prevTickSeconds + currentTickSeconds
当且仅当currentTickSeconds - prevTickSeconds
为0
时才会执行。
答案 1 :(得分:1)
为了让事情按照你想要的方式进行,你需要明确地告诉编译器它应该照顾唱歌,就像这样:
unsigned int prevTickSeconds = 48U;
unsigned int currentTickSeconds = 5U;
unsigned int secondsLeft = (((int) currentTickSeconds - (int) prevTickSeconds) > 0)
? currentTickSeconds - prevTickSeconds
: 60 - prevTickSeconds + currentTickSeconds;
或者,为了提高效率,您可能希望引入一个中间signed
值:
unsigned int prevTickSeconds = 48U;
unsigned int currentTickSeconds = 5U;
unsigned int secondsLeft = 0U;
{
signed int deltaSeconds = currentTickSeconds;
deltaSeconds -= prevTickSeconds;
secondsLeft = (deltaSeconds > 0)
? deltaSeconds
: 60 - deltaSeconds;
}
答案 2 :(得分:1)
C不关心你的算法,也不知道你的变量是否会下溢,也不知道下溢是故意的还是偶然的。无符号整数的欠/溢出是明确定义的行为,因此在这种情况下,编译器将很乐意按照您的要求执行操作:创建下溢。
一些细节:
unsigned int secondsLeft = (currentTickSeconds - prevTickSeconds ) ?
currentTickSeconds - prevTickSeconds :
60 - prevTickSeconds + currentTickSeconds;
如果我们将此表达式中的所有变量替换为相应的类型,我们得到:
unsigned int = (unsigned int - unsigned int) ?
unsigned int - unsigned int :
int - unsigned int + unsigned int;
所有C关心的是其隐式类型促销规则。此表达式中有两个这样的规则:常规平衡(通常的算术转换)和?:运算符的特殊平衡规则。
平衡规则规定,如果两个相同大小的整数是表达式的操作数,并且其中一个是无符号的,则带符号的操作数将转换为无符号操作数。
unsigned int = (unsigned int - unsigned int) ? // no conversion needed
unsigned int - unsigned int : // no conversion needed
(int - unsigned int) // convert the int to unsigned int
+ unsigned int; // we get unsigned + unsigned, no conversion needed
然后结果存储在unsigned int中。
然而,在C中有一个与条件运算符有关的特殊(奇怪)规则?:。第二个操作数和第三个操作数是平衡的,就好像它们是同一个表达式的运算符一样。所以,如果你有这种情况:
1 ? (signed int)x : (unsigned int)y;
然后结果将始终是unsigned int。这是因为x和y被视为它们是同一操作的一部分,即使y从未在代码中使用过。这可能会产生微妙的错误,在我看来,完全避免使用?:运算符是合理的。