[왕초보 임베디드-C 공부 일기] 11. 기본 자료형

C언어에서 자료형(Data Type) 은 메모리라는 거대한 창고에 데이터를 어떻게 해석할지 결정하는 그릇의 규격과 라벨 이다. 컴퓨터의 메모리 안에는 오직 0과 1밖에 없다. 똑같은 0100 0001이라는 데이터에도 이것을 '정수'로 만들지, '문자'로 읽을지에 따라 완전히 다른 의미가 된다. 위성이나 로버의 On-board 컴퓨터의 메모리는 데스크톱에 비해 용량이 매우 작기 때문에, 목적에 맞는 정확한 크기의 자료형을 선택하는 것이 매우 중요하다. C언어의 기본 자료형 4가지를 정의와 간단한 예시를 통해 알아본다.

1. 정수형 (Integer Types) "소수점이 없는 정확한 숫자"

음수와 양수, 혹은 양수만 표현할 수 있는 정수를 담는 그릇이다. (예 : signed char -> -128 ~ 127, unsigned char -> 0 ~ 255)

임베디드 실무의 절대 규칙 : 의 사용

C언어의 int는 컴파일러나 CPU 아키텍처(8비트, 32비트, 64비트)에 따라 크기가 고무줄처럼 변한다. 우주선 코드가 컴퓨터마다 다르게 동작하면 큰 문제가 발생한다. 따라서 실무에서는 크기가 명확하게 고정된 표준 정수형(Standard Integer Types) 을 100% 사용한다.

int8_t, uint8_t (1바이트)

숫자를 다룰 때에는 표준 정수형을 사용하여 부호를 강제하고, 통신으로 들어온 한 글자 그대로('A', 'W')를 다룰 때에만 예외적으로 char을 사용한다.

int16_t, uint16_t (2바이트)

대부분의 현대 시스템에서 short는 2바이트이지만, int16_t를 사용하면 컴파일러에게 "무조건 16비트짜리 공간을 달라."고 요구하는 것이다.

int32_t, uint32_t (4바이트)

C언어 표준에서 int는 "그 CPU가 가장 처리하기 편한 기본 데이터 크기(Word Size)" 를 따라가도록 정의되어 있다. STM32(32비트)에서 int가 4바이트라고 믿고 10만 단위의 숫자를 다루는 코드를 작성한다. 나중에 이 코드를 초소형 위성에 들어가는 8비트 칩으로 그대로 복사해서 넣으면, 8비트 칩에서 int는 2바이트(최대 32,767)이므로 숫자가 넘쳐서 치명적인 오작동이 발생할 수 있다. 여기서 int32_t 를 쓰면, 8비트 칩이든 32비트 칩이든 컴파일러가 무조건 4바이트(32비트) 공간을 만들어준다.

활용 사례 : 하드웨어 레지스터 제어 및 센서 값

#include 

uint32_t = encoder_pulse_count = 0; //0부터 4294967295까지 저장 가능

2. 실수형 (Floating-Point Types) : "소수점이 있는 정밀한 숫자"

소수점을 포함한 실수를 표현하는 자료형이다. IEEE 754라는 국제 표준 방식을 사용하며, 메모리를 '부호(Sign)', '지수(Exponent)', '가수(Fraction)' 세 부분으로 쪼개서 저장한다.

활용 사례 : 물리량 계산과 제어 알고리즘

float current_heading_angle = 45.5;
float target_angle = 90.0

//오차를 계산하여 조향 모터를 제어
float error = target_angle - current_heading_angle;
float steering_output = Kp * error; //kp도 float형 비례 상수

3. 문자형(Character Type) : "글자 탈을 쓴 작은 정수"

char(1바이트)는 문자를 표현하는 자료형이다. 하지만 컴퓨터는 문자를 모른다. 대신 ASCII(아스키) 코드라는 번역표를 사용하여 문자를 정수 번호로 바꿔서 저장한다.

활용 사례 : 통신 프로토콜 파싱(parsing)

char command = UART_Receive(); //통신으로 1바이트를 읽어옴

if (command == 'W') { // 내부적으로 if (command == 87) 과 똑같이 계산됨
	drive_forward();
}

4. 무치형 (Void Type) : "비어있음, 혹은 형태가 정해지지 않음"

void는 데이터를 담는 자료형이 아니다. "데이터의 자료형이 없다." 또는 "아무것도 반환하지 않는다." 는 것을 명시적으로 알려주는 키워드이다.

활용 사례 : 함수의 입출력 제어 및 범용 포인터

void SystemClock_Config(void) {
	//입력도 없고(void), 반환값도 없음(void). 그냥 세팅만 해놓는 역할이다. 
}

임베디드 펌웨어 작성 시 핵심 요약

  1. 0~255 사이의 작은 값ㅇ을 저장할 때 습관적으로 int(4바이트)를 쓰면 메모리가 낭비된다.
반드시 uint8_t 를 사용하는 것이 메모리 절약에 도움이 된다.
  1. 실무에서는 소스코드 위에 #include 를 가장 먼저 적고 시작하는 것이 기본 소양이다.
  2. 소수점 계산(float)은 CPU 성능을 깎아먹으므로, 꼭 필요한 곳(제어 수식 등)에서만 제한적으로 사용하는 것이 좋다.