Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    primarykey
    data
    text
    <p>When you use an arithmetic operator, the operands go through two conversions.</p> <p><strong>Integer promotions:</strong> If <code>int</code> can represent all values of the type, then the operand is promoted to int. This applies to both <code>short</code> and <code>unsigned short</code> on most platforms. The conversion performed on this stage is done on each operand individually, without regard for the other operand. (There are more rules, but this is the one that applies.)</p> <p><strong>Usual arithmetic conversions:</strong> If you compare an <code>unsigned int</code> against a <code>signed int</code>, since neither includes the entire range of the other, and both have the same rank, then both are converted to the <code>unsigned</code> type. This conversion is done after examining the type of both operands.</p> <p>Obviously, the "usual arithmetic conversions" don't always apply, if there are not two operands. This is why there are two sets of rules. One gotcha, for example, is that shift operators <code>&lt;&lt;</code> and <code>&gt;&gt;</code> don't do usual arithmetic conversions, since the type of the result should only depend on the left operand (so if you see someone type <code>x &lt;&lt; 5U</code>, then the <code>U</code> stands for "unnecessary").</p> <p><strong>Breakdown:</strong> Let's assume a typical system with 32-bit int and 16-bit short.</p> <pre><code>int a = -1; // "signed" is implied unsigned b = 2; // "int" is implied if (a &lt; b) puts("a &lt; b"); // not printed else puts("a &gt;= b"); // printed </code></pre> <ol> <li>First the two operands are promoted. Since both are <code>int</code> or <code>unsigned int</code>, no promotions are done.</li> <li>Next, the two operands are converted to the same type. Since <code>int</code> can't represent all possible values of <code>unsigned</code>, and <code>unsigned</code> can't represent all possible values of <code>int</code>, there is no obvious choice. In this case, both are converted to <code>unsigned</code>.</li> <li>When converting from signed to unsigned, 2<sup>32</sup> is repeatedly added to the signed value until it is in the range of the unsigned value. This is actually a noop as far as the processor is concerned.</li> <li>So the comparison becomes <code>if (4294967295u &lt; 2u)</code>, which is false.</li> </ol> <p>Now let's try it with <code>short</code>:</p> <pre><code>short c = -1; // "signed" is implied unsigned short d = 2; if (c &lt; d) puts("c &lt; d"); // printed else puts("c &gt;= d"); // not printed </code></pre> <ol> <li>First, the two operands are promoted. Since both can be represented faithfully by <code>int</code>, both are promoted to <code>int</code>.</li> <li>Next, they are converted to the same type. But they already are the same type, <code>int</code>, so nothing is done.</li> <li>So the comparison becomes <code>if (-1 &lt; 2)</code>, which is true.</li> </ol> <p><strong>Writing good code:</strong> There's an easy way to catch these "gotchas" in your code. Just always compile with warnings turned on, and fix the warnings. I tend to write code like this:</p> <pre><code>int x = ...; unsigned y = ...; if (x &lt; 0 || (unsigned) x &lt; y) ...; </code></pre> <p>You have to watch out that any code you do write doesn't run into the other signed vs. unsigned gotcha: signed overflow. For example, the following code:</p> <pre><code>int x = ..., y = ...; if (x + 100 &lt; y + 100) ...; unsigned a = ..., b = ...; if (a + 100 &lt; b + 100) ...; </code></pre> <p>Some popular compilers will optimize <code>(x + 100 &lt; y + 100)</code> to <code>(x &lt; y)</code>, but that is a story for another day. Just don't overflow your signed numbers.</p> <blockquote> <p>Footnote: Note that while <code>signed</code> is implied for <code>int</code>, <code>short</code>, <code>long</code>, and <code>long long</code>, it is NOT implied for <code>char</code>. Instead, it depends on the platform.</p> </blockquote>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. VO
      singulars
      1. This table or related slice is empty.
    2. VO
      singulars
      1. This table or related slice is empty.
    3. VO
      singulars
      1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload