← Embedded C 강의 목록으로
🔌
기초
기초 · 선수: 01강

02. 자료형·진수·stdint·sizeof

MCU의 레지스터는 폭이 정확히 정해져 있고(8/16/32비트) RAM은 수 KB뿐입니다. "이 변수가 정확히 몇 비트인가"가 곧 레지스터에 제대로 들어가는지를 결정합니다. stdint.h 의 폭 고정 타입이 왜 임베디드의 사실상 표준인지, 10진·16진·2진 표기, sizeof, 그리고 부호 없는 값이 최댓값을 넘을 때의 랩어라운드까지 PC의 gcc 로 직접 확인합니다.

stdintuint8_t진수16진수sizeof랩어라운드
소요 시간
약 1시간
난이도
📊 초급
선수 조건
🎯 01강
결과물
stdint.h 폭 고정 타입을 레지스터 폭과 연결해 고르고, 진수 표기·sizeof·랩어라운드를 정확히 이해해 임베디드 정수 함정을 피할 수 있습니다.

이 강의에서 배우는 것

  • 1C 기본 자료형 크기가 칩마다 다름을 이해한다(8051 int=16비트)
  • 2stdint.h 의 uint8_t/uint16_t/uint32_t 를 레지스터 폭과 연결해 쓴다
  • 3같은 수를 10진·16진·8진·2진으로 표기하고 printf 포맷으로 출력한다
  • 4sizeof 로 자료형의 바이트 크기를 확인한다
  • 5부호 없는 자료형의 랩어라운드와 부호 해석 차이를 이해한다

소개

PC에서는 int 가 몇 바이트인지 거의 신경 쓰지 않습니다. 하지만 임베디드에서는 "이 변수가 정확히 몇 비트인가"가 레지스터 적합성과 메모리 낭비를 좌우합니다. 이번 편은 보드 없이 순수 C 로직으로 자료형의 실체(폭)를 들여다봅니다.

핵심 개념

1) 자료형 크기는 칩마다 다르다

C 표준은 최소 크기만 보장하고 정확한 바이트 수는 컴파일러·칩이 정합니다. int 하나도 환경에 따라 폭이 다릅니다.

자료형8051(C51)ARM(MDK)PC(x86-64)
char111
int2(16비트)4(32비트)4(32비트)
long448

8051에서 `int count;` 로 50000까지 세려 하면 16비트 한계에 걸려 엉뚱한 값이 나옵니다. "int면 충분하겠지"라는 PC 습관이 깨지는 대표 지점입니다.

2) stdint.h — 폭이 이름에 박힌 타입

타입범위(unsigned)
uint8_t8비트0~255
uint16_t16비트0~65535
uint32_t32비트0~약 42억
  • 8비트 포트/레지스터(8051 P1) → uint8_t
  • 16비트 타이머 카운터 → uint16_t
  • 32비트 STM32 레지스터 → uint32_t

3) 진수와 printf 포맷

레지스터·비트는 16진수가 자연스럽습니다(16진 한 자리 = 4비트). 표기: 10진 `42`, 16진 `0x2A`, 8진 `052`(선행 0 주의!). 포맷: `%u`(10진), `%x`/`%X`(16진), `%o`(8진). 표준 printf 에는 2진 포맷이 없어 `(v>>i)&1` 로 직접 뽑습니다.

4) 랩어라운드와 부호 해석

c
uint8_t c = 255;
c = c + 1;   /* 256 이 아니라 0 (wrap-around) */

/* 같은 0xFF 비트도 부호 해석에 따라 다르다 */
/* (uint8_t)0xFF = 255, (int8_t)0xFF = -1 (2의 보수) */

핵심 예제

폭 고정 타입의 크기를 sizeof 로 찍고, 한 값(0x2A)을 여러 진수로 나란히 출력합니다.

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

int main(void)
{
    uint8_t reg = 0x2A;   /* 16진 0x2A = 10진 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

자주 하는 실수

Q. int 로 5만까지 셌는데 값이 이상해요.

A. 8051에서 int 는 16비트(부호 있으면 -32768~32767)입니다. 큰 수는 uint32_t(또는 unsigned long)를 쓰세요.

Q. for (uint8_t i = 10; i >= 0; i--) 가 끝나지 않아요.

A. 부호 없는 i 는 음수가 되지 않습니다. 0에서 i-- 하면 -1이 아니라 255로 랩어라운드되어 i >= 0 이 영원히 참입니다. 카운트다운엔 부호 있는 타입을 쓰거나 조건을 다시 설계하세요.

Q. 레지스터에서 읽은 0xFF 를 변수에 담았더니 -1이 나와요.

A. 받는 변수가 int8_t/signed char 면 0xFF 는 2의 보수로 -1입니다. "비트 묶음"은 부호 없는 타입(uint8_t)으로 받아야 255로 읽힙니다.

정리

  • 기본 자료형 크기는 칩마다 다르다(int: 8051 16비트, ARM/PC 32비트)
  • stdint.h 의 uint8_t/uint16_t/uint32_t 는 어디서나 1/2/4바이트 — 임베디드 표준
  • 레지스터·비트는 16진(0x)이 자연스럽고 선행 0(8진)에 주의한다
  • sizeof 로 실제 바이트 수를 확인한다
  • 부호 없는 값은 최댓값을 넘으면 0으로 랩어라운드된다

과제

  1. uint8_t 변수를 250부터 1씩 증가시키며 10회 출력해 255 다음 0으로 도는 것을 확인
  2. 0xA5 를 10진·16진·8진·2진으로 모두 출력하는 프로그램 작성
  3. sizeof(int) 와 sizeof(long) 을 PC gcc 로 찍어 본 뒤, 8051이라면 값이 어떻게 달라질지 표(핵심개념 1)와 비교
예제 코드 / 강의 자료

전체 강의 자료와 예제 코드(과제·정답 포함)는 GitHub에서 자유롭게 받아볼 수 있습니다.

GitHub에서 보기 ↗