03강. C언어 구조체와 함수 포인터 재발견

 03강. C언어 구조체와 함수 포인터 재발견

"왜 내 코드는 고칠 때마다 다른 데서 터질까?" 펌웨어 초보 시절 가장 많이 하는 고민이죠. 코드의 복잡성을 낮추고 전문가처럼 보이게 만드는 구조체와 함수 포인터 활용 꿀팁을 정리했습니다.

동료의 코드를 리뷰하다 보면, 온갖 소스 파일에 extern으로 얽혀있는 전역 변수 더미를 볼 때가 있습니다. 솔직히 말해서, 그런 코드는 나중에 기능 하나 추가하려면 전체를 다 뒤엎어야 하죠. 😭 저도 짬이 안 찼을 때는 구현에만 급급해서 "돌아가면 장땡이지!"라고 생각했습니다. 하지만 진짜 실력은 '남이 보기 편하고 고치기 쉬운 코드'에서 나옵니다. 오늘은 그 비결인 구조체와 함수 포인터 활용 팁을 소개할게요.

03강. C언어 구조체와 함수 포인터 재발견

TIP 1. 전역 변수 대신 '핸들(Handle)' 구조체를 쓰세요 📍

03강. C언어 구조체와 함수 포인터 재발견

센서 데이터를 읽을 때 temp_value라는 전역 변수를 쓰지 마세요. 대신 센서의 상태와 데이터를 모두 포함하는 구조체를 만들고, 함수의 인자로 그 구조체의 포인터(핸들)를 넘겨주세요. 이렇게 하면 하나의 소스 코드로 여러 개의 센서를 제어하는 것도 식은 죽 먹기입니다.

📌 핵심 체크포인트
- 전역 변수는 최소화한다.
- 모든 함수는 제어할 대상의 포인터를 인자로 받는다 (예: Sensor_Read(&h_sensor1)).

 

TIP 2. 함수 포인터로 '콜백(Callback)' 구현하기 🔔

03강. C언어 구조체와 함수 포인터 재발견

펌웨어에서 인터럽트 처리는 매우 중요하죠. 하지만 인터럽트 핸들러 안에 비즈니스 로직을 직접 넣으면 코드가 엉망이 됩니다. 이때 구조체 안에 등록(Registration)용 함수 포인터를 만드세요. 특정 이벤트가 발생했을 때 미리 등록된 함수를 호출하게 하면, 모듈 간의 결합도가 획기적으로 낮아집니다.

Before vs After 설계 비교

  • Before: UART 인터럽트 함수 안에서 직접 패킷을 분석하고 메인 로직 변수를 수정함.
  • After: UART 드라이버 구조체에 on_rx_complete 포인터를 두고, 메인에서 원하는 함수를 연결함.

 

TIP 3. 주의해야 할 '흔한 실수' ⚠️

03강. C언어 구조체와 함수 포인터 재발견

함수 포인터가 강력하긴 하지만, 남용하면 디버깅이 지옥이 될 수 있습니다. 호출 스택을 따라가기 힘들어지기 때문이죠. 따라서 다음과 같은 원칙을 지키는 것이 좋습니다.

⚠️ 주의하세요!
1. 함수 포인터 호출 전에는 반드시 NULL 체크를 하세요. (안 하면 하드폴트 납니다!)
2. 너무 깊은 단계의 함수 포인터 중첩은 피하세요. 가독성이 안드로메다로 갑니다.

 

03강. C언어 구조체와 함수 포인터 재발견

실무 설계 3계명

1. 데이터 그룹화: 무조건 구조체로 묶어라.
2. 인터페이스화: 하드웨어 제어는 함수 포인터 뒤에 숨겨라.
3. 안전 우선: 함수 포인터 사용 시 반드시 if(ptr != NULL)를 확인하라.

자주 묻는 질문 ❓

03강. C언어 구조체와 함수 포인터 재발견
Q: 함수 포인터를 사용하면 정적 분석 툴에서 경고가 뜨지 않나요?
A: MISRA C 같은 엄격한 표준에서는 함수 포인터 사용을 제한하기도 합니다. 하지만 현대적인 아키텍처에서는 안전하게 사용한다는 전제하에 필수적인 요소로 인정받습니다.
Q: 구조체 안에 함수 포인터를 넣으면 메모리를 많이 먹지 않나요?
A: 포인터 하나당 4바이트(32비트 기준)입니다. 수십 개의 인스턴스를 만드는 게 아니라면 RAM 사용량에 큰 타격은 없으니 안심하세요!

기술적인 정답은 없지만, 유지보수하기 좋은 코드가 결국 이기는 코드입니다. 오늘 배운 팁들을 여러분의 프로젝트에 하나씩 적용해 보세요. 분명 코드 리뷰 때 선배들의 눈빛이 달라질 겁니다! 😉

03강. C언어 구조체와 함수 포인터 재발견


다음 이전