← Back to Embedded C series
🔌
Basics
Basics · Prereq: lesson 1

02. Data Types · Radix · stdint · sizeof

An MCU's registers have exact widths (8/16/32-bit) and RAM is only a few KB. "Exactly how many bits is this variable?" decides whether it fits a register. We look at the reality of types (their width): why stdint.h's fixed-width types are the de-facto embedded standard, radix notation, sizeof, and the wrap-around when an unsigned value exceeds its max — all verified with PC gcc.

stdintuint8_tradixhexsizeofwrap-around
Duration
~1 hour
Level
📊 Beginner
Prerequisite
🎯 Lesson 1
OUTCOME
Pick stdint.h fixed-width types by register width and understand radix·sizeof·wrap-around to avoid embedded integer pitfalls.

What you'll learn

  • 1Understand that basic type sizes vary by chip (8051 int=16-bit)
  • 2Use stdint.h's uint8_t/uint16_t/uint32_t tied to register width
  • 3Print a value in decimal·hex·octal·binary with printf formats
  • 4Confirm a type's byte size with sizeof
  • 5Understand unsigned wrap-around and signedness reinterpretation

Introduction

On a PC you rarely care how many bytes an int is. In embedded, "exactly how many bits" decides register fit and memory waste. This lesson examines the reality of types (their width) with pure C logic, no board needed.

Key concepts

1) Type sizes vary by chip

Type8051(C51)ARM(MDK)PC(x86-64)
char111
int2 (16-bit)4 (32-bit)4 (32-bit)
long448

On 8051, `int count;` counting to 50000 overflows the 16-bit limit and gives garbage. The PC habit "int is enough" breaks here.

2) stdint.h — width baked into the name

TypeWidthRange (unsigned)
uint8_t8-bit0–255
uint16_t16-bit0–65535
uint32_t32-bit0–~4.29B
  • 8-bit port/register (8051 P1) → uint8_t
  • 16-bit timer counter → uint16_t
  • 32-bit STM32 register → uint32_t

3) Radix and printf formats

Hex is natural for registers·bits (one hex digit = 4 bits). Notation: decimal `42`, hex `0x2A`, octal `052` (beware a leading 0!). Formats: `%u` (dec), `%x`/`%X` (hex), `%o` (oct). Standard printf has no binary format, so extract bits with `(v>>i)&1`.

4) Wrap-around and signedness

c
uint8_t c = 255;
c = c + 1;   /* 0, not 256 (wrap-around) */

/* The same 0xFF bits read differently by signedness */
/* (uint8_t)0xFF = 255, (int8_t)0xFF = -1 (two's complement) */

Core example

Print fixed-width sizes with sizeof and show one value (0x2A) side by side in several radixes.

c
#include <stdio.h>
#include <stdint.h>

int main(void)
{
    uint8_t reg = 0x2A;   /* hex 0x2A = decimal 42 */
    printf("sizeof(uint8_t)  = %u\n", (unsigned)sizeof(uint8_t));
    printf("sizeof(uint32_t) = %u\n", (unsigned)sizeof(uint32_t));
    printf("dec=%u hex=0x%02X oct=0%o\n", (unsigned)reg, reg, reg);
    return 0;
}
// dec=42 hex=0x2A oct=052
bash
gcc main.c -o main && ./main

Common mistakes

Q. I counted to 50000 with int and got weird values.

A. On 8051, int is 16-bit (signed: -32768–32767). Use uint32_t (or unsigned long) for large numbers.

Q. for (uint8_t i = 10; i >= 0; i--) never ends.

A. An unsigned i is never negative. At 0, i-- wraps to 255 (not -1), so i >= 0 stays true forever. Use a signed type for countdowns, or redesign the condition.

Q. I stored 0xFF read from a register and got -1.

A. If the receiving variable is int8_t/signed char, 0xFF is -1 (two's complement). Receive "bit bundles" in an unsigned type (uint8_t) to read 255.

Summary

  • Basic type sizes vary by chip (int: 16-bit on 8051, 32-bit on ARM/PC)
  • stdint.h's uint8_t/uint16_t/uint32_t are 1/2/4 bytes everywhere — the embedded standard
  • Hex (0x) is natural for registers·bits; beware a leading 0 (octal)
  • sizeof confirms the real byte count
  • Unsigned values wrap to 0 past their max

Exercises

  1. Increment a uint8_t from 250 by 1 ten times and watch 255 wrap to 0
  2. Write a program that prints 0xA5 in decimal·hex·octal·binary
  3. Print sizeof(int)/sizeof(long) on PC gcc, then compare with the 8051 row of the table
Example code / lecture materials

All lecture materials and example code (with homework and answers) are openly available on GitHub.

View on GitHub ↗