나의 C23 코딩 관례
요약
본 글은 C 언어의 최신 표준인 C23에서 도입된 `constexpr`와 `static_assert`를 활용하여 컴파일 타임에 강력한 검증 및 상수 표현식을 구현하는 방법을 다룹니다. 이를 통해 복잡한 전처리 과정 없이도 안정적이고 현대적인 코딩 관례를 확립할 수 있음을 강조합니다.
핵심 포인트
- C23의 constexpr와 static_assert로 컴파일 타임 검증 강화
- 전처리기 의존도를 낮추고 C++까지 동원할 필요 감소
- 구조체 공용체의 0 초기화 문제 해결 및 표준 개선 기대
constexpr 가 진짜 컴파일 타임 상수 표현식을 제공한다는 이유만으로 거의 C23만 고집해서 사용함. 오래전부터 절실했던 기능임.
정수 상수를 만들려고 익명 열거형을 편법으로 쓰고, 다른 종류의 상수에는 전처리기를 써야 하는 게 늘 싫었음. 그래도 열거형은 언어 기능이라 디버거에도 표시되니 전처리기보다는 나은 편임. const 객체는 단지 변경 불가능할 뿐 컴파일 타임 상수는 아니므로, 정적 배열의 길이 같은 곳에 반드시 쓸 수 있는 것은 아님.
C23의 constexpr와 static_assert 를 함께 쓰면 컴파일 타임에 많은 검증이 가능함. 이 예제, 전처리기를 조금 활용한 예제, 주변 장치 설정이 그런 경우임.
C를 더 쓰기 좋은 언어로 만들어 주고, 단순한 작업에서는 이런 컴파일 타임 기법 덕분에 C++까지 동원할 필요가 없어짐.
Clang에서 복합 리터럴에 대한 constexpr 가 컴파일은커녕 구문 분석조차 안 되는 게 정말 짜증 남.
전역 constexpr 상수도 C2Y 전까지는 쓰기 어려움. constexpr 변수는 암묵적으로 inline이고, 비정적 인라인 함수가 정적 전역 변수에 의존하면 컴파일러가 오류를 내야 하므로 비정적 인라인 함수 안에서 사용할 수 없기 때문임.
예전에는 C의 0 초기화를 도무지 믿지 못했음. {}와 {0} 중 무엇이 맞는지, 예외는 없는지 늘 헷갈려서 변수 선언 뒤에 명시적으로 memset을 호출하곤 함. 그러다 지쳐서 올바른 문법을 찾아보고 {0}을 쓰기 시작함.
이제는 내가 아니라 C가 문제인 건 아닌지 의문이 듦.
{0}이 구조체 내부 공용체 전체의 0 초기화를 보장하지 않는 것은 분명 잘못된 설계임. C 표준은 공용체의 첫 번째 멤버만 0으로 초기화하도록 요구하므로, 첫 멤버가 나머지보다 크도록 배치해야 함.
더 황당한 건 예전에는 gcc가 전체를 0으로 초기화하고 clang은 그러지 않았는데, 지난해에는 서로 정반대로 바뀌었다는 것임. 대체 무슨 일인지 모르겠음.
C23에서는 {} 로 이 난장판을 해결해서 이제 어디서나 사용하며, 잘 동작함. 정작 0이 들어간 {0}이 기대한 동작을 확실히 보장하지 않는 건 이상함. 표준 위원회가 기존 문법의 의미를 바꾸지 않으려는 듯하지만, auto는 바꾸지 않았나 싶음.
AI 자동 생성 콘텐츠
본 콘텐츠는 GeekNews의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기