<!--order=3-->


<h1>Data Types Part 2 - Signed and Unsigned Values</h1>
<p>The bit pattern in a register does not carry its own signedness. The program, instruction, or data format decides whether those bits represent an unsigned magnitude or a signed two's-complement value. This matters when working with AArch64 registers, C integer types, binary protocols, and debuggers.</p>

<h2>AArch64 Register Views</h2>
<p>AArch64 has 31 general-purpose registers. The <code>xN</code> name refers to the full 64-bit register, while <code>wN</code> refers to the lower 32 bits of the same register:</p>
<pre>
x5  // all 64 bits of general-purpose register 5
w5  // the low 32 bits of general-purpose register 5
</pre>
<p>Writing a result to <code>w5</code> also clears the upper 32 bits of <code>x5</code>. This zero-extension is an important architectural rule:</p>
<pre>
mov x5, #0xffff
mov w5, #1       // x5 is now 0x0000000000000001
</pre>
<p>The <code>xN</code> and <code>wN</code> names describe width; they do not by themselves say whether a value is signed.</p>

<h2>Unsigned Values</h2>
<p>An unsigned <code>n</code>-bit value uses every bit for its magnitude and ranges from <code>0</code> through <code>2^n - 1</code>:</p>
<pre>
Unsigned 32-bit:
0x00000000 = 0
0xffffffff = 4,294,967,295

Unsigned 64-bit:
0x0000000000000000 = 0
0xffffffffffffffff = 18,446,744,073,709,551,615
</pre>

<h2>Signed Two's-Complement Values</h2>
<p>A signed <code>n</code>-bit two's-complement value ranges from <code>-2^(n-1)</code> through <code>2^(n-1)-1</code>. When the MSB is set, the same bits are interpreted as a negative value:</p>
<pre>
Signed 32-bit:
0x80000000 = -2,147,483,648
0xffffffff = -1
0x00000000 = 0
0x7fffffff = 2,147,483,647
</pre>
<p><code>0xffffffff</code> is therefore <code>4,294,967,295</code> as an unsigned 32-bit value and <code>-1</code> as a signed 32-bit value. Nothing changed in the bits; only the interpretation changed.</p>

<h2>Ranges at a Glance</h2>
<table>
  <thead><tr><th>Width</th><th>Unsigned range</th><th>Signed range</th></tr></thead>
  <tbody>
    <tr><td>32 bits</td><td>0 to 4,294,967,295</td><td>-2,147,483,648 to 2,147,483,647</td></tr>
    <tr><td>64 bits</td><td>0 to 18,446,744,073,709,551,615</td><td>-9,223,372,036,854,775,808 to 9,223,372,036,854,775,807</td></tr>
  </tbody>
</table>

<h2>Signedness in C</h2>
<p>Choose the C type that describes the data instead of relying on a cast at the last moment:</p>
<pre>
#include &lt;stdint.h&gt;

uint32_t packet_length = 0xffffffffu;
int32_t temperature_delta = -1;
</pre>
<p>Be careful when signed and unsigned values meet in an expression. C's usual arithmetic conversions can convert a negative signed value to a very large unsigned value. Make the conversion explicit and validate external values before using them as sizes, indexes, or allocation lengths.</p>

<h2>Inspecting Values in a Debugger</h2>
<p>When a register looks surprising, print or inspect it in more than one representation. In GDB, the format letters below show the same register as hexadecimal, unsigned decimal, and signed decimal:</p>
<pre>
(gdb) p/x $x0
(gdb) p/u $x0
(gdb) p/d $x0
</pre>
<p>Always write down the width and signedness you intended. “The register contains a negative number” is incomplete without saying which width and interpretation produced that conclusion.</p>

<h2>Connection to Memory and Data Types</h2>
<p>The companion <a href="categories.php?cat=Code&amp;article=Memory%20and%20Data%20Types">Memory and Data Types</a> guide covers binary, hexadecimal, storage widths, fixed-width C types, and byte order. Use this article when the question is specifically about interpreting a value as signed or unsigned.</p>

<h2>References</h2>
<ul>
  <li><a href="https://developer.arm.com/documentation/102374/latest" target="_blank" rel="noopener">Arm A64 Instruction Set Architecture Guide ↗</a></li>
  <li><a href="https://en.cppreference.com/w/c/language/conversion.html" target="_blank" rel="noopener">C implicit conversions ↗</a></li>
  <li><a href="https://en.wikipedia.org/wiki/Two%27s_complement" target="_blank" rel="noopener">Two's complement ↗</a></li>
</ul>