1

unsigned三項演算子条件で型のみを使用すると、これらのunsigned変数は自動的にsigned型に変換されますか?

簡単な例:

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

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

この例のような場合、この構造は適切に機能し(currentTickSeconds > prevTickSeconds)ますか? 三項演算子の条件は自動で型変換するか?

4

3 に答える 3

5

いいえ、すべての型がunsigned intそうであり、「アンダーフロー」があるため、そのような変換はありません。

ノート:

60 - prevTickSeconds + currentTickSeconds

の場合にのみ実行されcurrentTickSeconds - prevTickSecondsます0

于 2012-11-08T07:56:35.350 に答える
1

物事を思いどおりに進めるには、次のように、singn を処理する必要があることをコンパイラに明示的に伝える必要があります。

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;  
}
于 2012-11-08T08:10:27.390 に答える
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 が気にするのは、その暗黙的な型昇格規則だけです。この式には、通常のバランス (通常の算術変換) と ?: 演算子の特別なバランス ルールの 2 つのルールがあります。

バランス規則では、同じサイズの 2 つの整数が式のオペランドであり、そのうちの 1 つが符号なしである場合、符号付きオペランドは符号なしオペランドに変換されると規定されています。

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 には、条件演算子 ?: に関連する特別な (奇妙な) ルールがあります。第 2 オペランドと第 3 オペランドは、同じ式の演算子であるかのようにバランスが取れています。したがって、このケースがある場合:

1 ? (signed int)x : (unsigned int)y;

結果は常に unsigned int になります。これは、コード内で y が使用されていないにもかかわらず、x と y が同じ操作の一部であるかのように扱われるためです。これは微妙なバグを引き起こす可能性があり、私の意見では、?: 演算子を完全に避けるのに十分な理由です。

于 2012-11-08T08:29:13.327 に答える