임베디드 면접 용어 사전
임베디드 C++

zero-overhead 원칙

쓰지 않는 기능에 비용을 물리지 않는다는 C++ 설계 원칙. 예외·RTTI는 이 원칙의 예외로 다뤄진다.

C++의 설계 철학. "쓰지 않는 것에는 비용을 내지 않고, 쓰는 것은 직접 구현한 것보다 느리지 않다" (Bjarne Stroustrup).

What you don't use, you don't pay for. What you do use, you couldn't hand-code any better.

무엇이 무료인가 — 임베디드에서 안심하고 쓸 수 있는 것

기능비용
클래스·멤버 함수없음. this를 첫 인자로 넘기는 함수와 동일
네임스페이스없음. 컴파일 시점 개념
템플릿없음(런타임). 컴파일 시 코드 생성
constexpr없음. 컴파일 시 계산
참조없음. 포인터와 같은 코드
인라인·operator 오버로딩없음
static_cast없음. 컴파일 시 검사
강한 타입 열거(enum class)없음
RAII없음. 소멸자 호출이 그대로 코드가 됨

클래스를 쓴다고 느려지지 않는다.

class Led { uint32_t pin; public: void on() { GPIOA->BSRR = pin; } };
led.on();
// → 컴파일 결과는 C의 led_on(&led) 와 동일하다

무엇이 비용을 갖는가

기능비용임베디드에서
가상 함수vptr + 간접 호출필요한 곳에만
예외테이블 수 KB~수십 KB, 스택 되감기보통 끈다
RTTI타입 정보 테이블보통 끈다
동적 할당단편화, 비결정적 시간피한다
iostream매우 크다(수십 KB)쓰지 않는다
std::function힙 할당 가능주의

"쓰지 않으면 비용이 없다" 는 원칙 덕분에, 이것들을 안 쓰면 그만큼의 비용이 사라진다.

-fno-exceptions -fno-rtti -fno-threadsafe-statics

예외를 끄는 이유

  • ① 코드 크기 — 스택 되감기 테이블이 크다
  • ② 비결정적 — throw 부터 catch 까지 시간을 예측할 수 없다
  • ③ 메모리 — 예외 객체 할당에 힙을 쓸 수 있다
  • ④ 대안 부재 — 예외를 못 잡으면 std::terminate → 시스템 정지

대신 오류 코드나 std::expected(C++23) 스타일을 쓴다.

// -fno-exceptions 이면 표준 라이브러리의 throw 도 abort 가 된다
// std::vector::at() 같은 것을 쓰면 안 된다

템플릿 — 강력하지만 코드 팽창 주의

template <typename T> T max(T a, T b) { return a > b ? a : b; }
max(1, 2);        // int 버전 생성
max(1.0, 2.0);    // double 버전 생성
max<uint8_t>(…);  // 또 하나

타입마다 별도 코드가 생성된다. 남용하면 플래시가 부풀어 오른다.

// 공통 부분을 비템플릿 함수로 빼는 기법
template <typename T> void process(T *p, size_t n) {
    process_impl(static_cast<void*>(p), n, sizeof(T));   // 실체는 하나
}

constexpr — 런타임 비용을 컴파일 시점으로

constexpr uint32_t baud_to_brr(uint32_t clk, uint32_t baud) {
    return (clk + baud / 2) / baud;
}
constexpr uint32_t BRR = baud_to_brr(84000000, 115200);   // 컴파일 시 계산
USART1->BRR = BRR;    // 상수 대입 명령 하나

계산이 플래시의 상수로 바뀐다. 매크로보다 안전하면서 비용은 같다. 임베디드 C++에서 가장 활용 가치가 높은 기능 중 하나다.

RAII — 임베디드에서 유용한 패턴

class CriticalSection {
    uint32_t primask;
public:
    CriticalSection() { primask = __get_PRIMASK(); __disable_irq(); }
    ~CriticalSection() { __set_PRIMASK(primask); }
};

void f() {
    CriticalSection cs;      // 진입
    // …
    if (error) return;       // ★ 어느 경로로 나가도 자동 복원
}                            // 소멸자가 인터럽트를 복원

★ 해제를 빠뜨릴 수 없다. C에서 goto cleanup으로 하던 것을 언어가 보장해 준다. 비용은 0이고 안전성만 얻는다.

실무 지침

✅ 클래스, 네임스페이스, constexpr, enum class, RAII, 템플릿(절제)

  • ⚠️ — 가상 함수 — 필요한 추상화에만 ❌ 예외, RTTI, iostream, 동적 할당, std::function(힙 할당 시)

"C++을 쓰되 부분집합을 쓴다" 가 임베디드의 현실적 답이다. MISRA C++와 AUTOSAR C++14 가이드라인이 이 부분집합을 규정한다.

함께 보면 좋은 용어

노트에서 맥락과 함께 보기 — 임베디드 C++·코드 품질 — vtable·예외/RTTI·동적할당·MISRA·volatile