title: C++ Standard: Strange signed/unsigned arithmetic division behavior for 32 and 64 bits
body: <p>I encountered a wrong behavior of my code. Investigating it leads me to a short example which shows the problem:</p>
  
  <pre><code>//g++  5.4.0
  
  #include &lt;iostream&gt;
  #include &lt;vector&gt;
  
  int main()
  {
      std::vector&lt;short&gt; v(20);
  
      auto D = &amp;v[5] - &amp;v[10];   
      auto C = D / sizeof(short);
  
      std::cout &lt;&lt; "C = " &lt;&lt; C;
  
  }
  </code></pre>
  
  <p>The example is a quite common. What is the result it will print?</p>
  
  <pre><code>C = 9223372036854775805
  </code></pre>
  
  <p>Tested here: <a href="https://rextester.com/l/cpp_online_compiler_gcc" rel="nofollow noreferrer">https://rextester.com/l/cpp_online_compiler_gcc</a>
  Tested also for <strong>Clang C++</strong>, <strong>VS C++</strong> and <strong>C</strong>. Result the same.</p>
  
  <p>Discussing with colleagues I was pointed to the document <a href="https://en.cppreference.com/w/cpp/language/operator_arithmetic#Conversions" rel="nofollow noreferrer">https://en.cppreference.com/w/cpp/language/operator_arithmetic#Conversions</a> .</p>
  
  <p>It tells:</p>
  
  <ul>
  <li>If both operands are signed or both are unsigned, the operand with lesser conversion rank is converted to the operand with the greater integer conversion rank</li>
  <li>Otherwise, if the unsigned operand's conversion rank is greater or equal to the conversion rank of the signed operand, the signed operand is converted to the unsigned operand's type. </li>
  <li>Otherwise, if the signed operand's type can represent all values of the unsigned operand, the unsigned operand is converted to the signed operand's type</li>
  </ul>
  
  <p>It seems the <strong>second</strong> rule is working here. But it is <strong>not</strong> true.</p>
  
  <p>To confirm the <strong>second</strong> rule, I have tested such example:</p>
  
  <pre><code>//g++  5.4.0
  #include &lt;iostream&gt;
  
  int main()
  {
              typedef uint32_t u_t; // uint64_t, uint32_t, uint16_t uint8_t
              typedef int32_t i_t;  // int64_t, int32_t, int16_t int8_t
  
              const u_t B = 2;
              const i_t X = -1;
  
              const i_t A1 = X * B;
      std::cout &lt;&lt; "A1 = X * B = " &lt;&lt; A1 &lt;&lt; "\n";
  
              const i_t C = A1 / B;  // signed / unsigned division
      std::cout &lt;&lt; "A1 / B = " &lt;&lt; C &lt;&lt; "\n";
  }
  </code></pre>
  
  <p>with different <em>rank</em> combinations of <em>u_t</em> and <em>i_t</em> and found that it works correctly for any combination, <strong>EXCEPT</strong> for <em>32</em> and <em>64</em> bits (<em>int64_t/uint64_t</em> and <em>int32_t/uint32_t</em>). So the <em>second</em> rule <strong>DOES NOT</strong> work for <em>16</em> and <em>8</em> bits.</p>
  
  <p>Note: the <em>multiplication</em> operation is working correct for all cases. So it is only <strong>division</strong> problem. </p>
  
  <p>Also the <strong>SECOND</strong> rule sounds like it is wrong:</p>
  
  <blockquote>
    <p>the signed operand is converted to the unsigned operand's type</p>
  </blockquote>
  
  <p>The <em>signed</em> cannot be converted to <em>unsigned</em> - it is an <strong>!! error !!</strong> for <strong>NEGATIVE</strong> values!!
  But opposite conversion is correct - <em>the unsigned operand is converted to the signed operand's type</em></p>
  
  <p>Looking at this I can note that here is a possible mistake in the C++ Standard Arithmetic operations. 
  Instead of:</p>
  
  <p><code>Otherwise, if the unsigned operand's conversion rank is greater or equal to the conversion rank of the signed operand, the signed operand is converted to the unsigned operand's type.</code></p>
  
  <p>it SHALL be:</p>
  
  <p><code>Otherwise, if the signed operand's conversion rank is greater or equal to the conversion rank of the unsigned operand, the unsigned operand is converted to the signed operand's type.</code></p>
  
  <p>On my opinion, if <em>signed</em> and <em>unsigned</em> <em>multiplication</em>/<em>division</em> is met then <em>unsigned</em> operand is converted to <em>signed</em> and after that it is casted to correct rank. At least the <em>x86 Assembler</em> follows it.</p>
  
  <p>Please, explain me where here is an error. I want the first test in this post works correct for any type involved in place of the <strong>auto</strong> type, but now it is <strong>not</strong> possible and the <em>C++ Standard</em> tells that it is correct behavior.</p>
  
  <p>Sorry for a strange question, but I am in a stuck with the problem. I am coding on C/C++ for 30 years but it is first problem I cannot explain it clearly - whether it is a bug or an expected behavior.</p>