三元运算符。在条件下自动键入转换

时间:2012-11-08 07:51:51

标签: c ternary-operator

如果我在三元运算符条件中仅使用unsigned类型,这些unsigned变量会自动转换为signed类型吗?

简单示例:

unsigned int prevTickSeconds = 48;
unsigned int currentTickSeconds = 5; 

unsigned int secondsLeft = (currentTickSeconds - prevTickSeconds ) ?
                            currentTickSeconds - prevTickSeconds :
                            60 - prevTickSeconds + currentTickSeconds;  

如本示例所示,(currentTickSeconds > prevTickSeconds)时此构造是否正常工作?是否会为三元运算符中的条件自动执行类型转换?

3 个答案:

答案 0 :(得分:5)

不,没有这样的转换,因为所有类型都是unsigned int并且会出现“下溢”。

注:

60 - prevTickSeconds + currentTickSeconds
当且仅当currentTickSeconds - prevTickSeconds0时才会执行

答案 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从未在代码中使用过。这可能会产生微妙的错误,在我看来,完全避免使用?:运算符是合理的。