ISO C
1. 개요
1. 개요
ISO C는 C 프로그래밍 언어의 공식적인 국제 표준이다. 이 표준은 국제 표준화 기구(ISO)와 국제 전기 표준 회의(IEC)가 공동으로 제정 및 관리하며, 공식 명칭은 ISO/IEC 9899이다. 최초의 ISO C 표준은 1990년에 제정되었다. 이 표준은 C 언어의 문법, 키워드, 자료형, 그리고 핵심 표준 라이브러리에 대한 명세를 정의함으로써, 서로 다른 컴파일러와 운영 체제 간에 높은 수준의 이식성을 보장하는 코드를 작성할 수 있는 기반을 마련한다.
ISO C는 주로 시스템 프로그래밍 분야에서 널리 사용된다. 그 명확한 정의와 효율성 덕분에 운영 체제 커널, 장치 드라이버, 컴파일러 및 임베디드 시스템 소프트웨어 개발에 적합한 언어로 자리 잡았다. 또한, 이식성이 높은 응용 소프트웨어를 개발하는 데에도 중요한 역할을 한다. 이 표준은 프로그래밍 언어 표준화, 소프트웨어 공학, 그리고 시스템 프로그래밍 분야와 깊은 연관이 있다.
표준의 제정과 유지는 ISO와 IEC의 합동 기술 위원회인 ISO/IEC JTC 1 산하의 WG14 워킹 그룹에서 담당한다. 이 그룹은 언어의 진화를 논의하고, 새로운 기능을 추가하거나 기존 기능을 명확히 하는 개정 작업을 수행한다. 시간이 지남에 따라 C99, C11, C17, C23과 같은 주요 개정판이 발표되어 언어에 새로운 기능이 도입되고 명세가 개선되었다.
2. 역사
2. 역사
2.1. 초기 표준화 과정
2.1. 초기 표준화 과정
C 언어의 초기 표준화 과정은 1980년대 초반에 시작되었다. 당시 C 언어는 데니스 리치와 브라이언 커니핸이 쓴 책 *The C Programming Language*에 기술된 내용, 즉 K&R C를 사실상의 표준으로 삼아 널리 사용되고 있었다. 그러나 이는 공식 표준이 아니었기 때문에, 서로 다른 컴파일러와 시스템 간에 미묘한 차이와 호환성 문제가 발생했다. 이러한 문제를 해결하고 언어의 이식성을 높이기 위해 ANSI가 주도하여 표준화 작업에 착수했다.
ANSI는 1983년에 X3J11 위원회를 구성하여 C 언어의 공식 미국 국가 표준을 제정하는 작업을 시작했다. 이 위원회는 기존의 다양한 C 구현체와 K&R C를 기반으로 하여, 언어의 핵심 문법과 표준 라이브러리를 엄밀하게 정의하는 데 주력했다. 표준화 과정은 수년에 걸쳐 진행되었으며, 여러 차례의 초안을 거쳐 1989년에 ANSI X3.159-1989 표준이 공식적으로 승인되었다. 이 표준은 흔히 ANSI C 또는 C89라고 불린다.
ANSI C 표준이 제정된 직후, 국제 표준화 기구(ISO)와 국제 전기 표준 회의(IEC)는 이 표준을 국제 표준으로 채택하기 위한 절차를 진행했다. ISO/IEC JTC 1/SC 22 위원회는 ANSI C 표준을 검토하여 약간의 편집상 변경만을 가한 후, 1990년에 ISO/IEC 9899:1990 Programming languages — C를 공표했다. 이로써 C 언어는 최초의 공식적인 국제 표준을 갖추게 되었으며, 이 표준은 ANSI C와 실질적으로 동등한 내용을 담고 있어 C90이라고도 불린다. 이 초기 표준화는 C 언어의 확산과 이식성 보장에 결정적인 기반을 마련했다.
2.2. ANSI C (C89/C90)
2.2. ANSI C (C89/C90)
ANSI C는 미국 국립 표준 협회가 1989년에 채택한 C 프로그래밍 언어의 공식 표준이다. 이 표준은 종종 C89라고 불리며, 이후 1990년에 국제 표준화 기구와 국제 전기 표준 회의에 의해 약간의 편집상 변경만을 거쳐 ISO/IEC 9899:1990으로 채택되어 C90이라고도 불린다. 이는 C 언어 역사상 최초의 공식적인 표준안으로, 그 이전까지 널리 사용되던 비공식적인 K&R C의 여러 모호함과 구현 의존적 요소를 명확히 규정하는 데 주된 목적이 있었다.
이 표준의 제정은 C 언어의 급속한 확산과 다양한 컴파일러 구현 사이의 호환성 문제를 해결하기 위한 노력의 결과였다. ANSI 위원회 X3J11은 데니스 리치와 브라이언 커니핸이 저술한 'The C Programming Language' 책을 기반으로 하여, 기존의 관행을 조사하고 언어의 핵심을 공식화하는 작업을 진행했다. 이를 통해 함수 프로토타입, void 및 const 키워드의 도입, 표준 헤더 파일 세트의 정의 등 중요한 새로운 기능들이 언어에 추가되었다.
ANSI C 표준은 크게 두 부분으로 구성된다. 첫 번째는 언어의 핵심 문법과 의미를 규정하는 부분이며, 두 번째는 표준 라이브러리를 정의하는 부분이다. 표준 라이브러리는 입출력, 문자열 처리, 수학 함수, 메모리 관리 등을 위한 일관된 인터페이스를 제공하여, 서로 다른 하드웨어 플랫폼과 운영 체제에서도 이식성 높은 코드 작성이 가능하도록 했다. 이는 특히 시스템 프로그래밍과 임베디드 시스템 개발 분야에서 큰 장점으로 작용했다.
ANSI C의 채택은 C 언어의 발전에 있어 결정적인 분기점이 되었다. 하나의 공통된 명세를 따르게 됨으로써, 개발자들은 특정 벤더의 확장 기능에 의존하지 않고도 안정적이고 호환 가능한 코드를 작성할 수 있게 되었다. 이 표준은 이후 모든 현대 C 표준의 기초가 되었으며, C99, C11, C17 및 최신의 C23 표준이 이를 계승하여 발전시켜 나갔다.
2.3. ISO/IEC 9899:1999 (C99)
2.3. ISO/IEC 9899:1999 (C99)
ISO/IEC 9899:1999, 흔히 C99으로 불리는 이 표준은 1999년에 공개된 C 언어의 국제 표준이다. 이는 1990년에 제정된 초판(C90) 이후 약 10년 만에 이루어진 주요 개정판으로, 현대적인 프로그래밍 요구사항을 반영하고 언어 기능을 상당히 확장했다. C99의 개발은 ANSI 위원회와 ISO/IEC JTC 1/SC 22의 공동 작업 그룹인 WG14가 주도했다.
C99 표준은 언어에 여러 중요한 기능을 추가했다. 대표적으로, 인라인 함수를 공식적으로 지원하여 함수 호출 오버헤드를 줄였고, C++ 스타일의 // 한 줄 주석을 허용하여 편의성을 높였다. 또한, 가변 길이 배열(VLA)을 도입하여 런타임에 배열 크기를 결정할 수 있게 했으며, 복소수 자료형을 표준 라이브러리에 포함시켜 과학 및 공학 계산을 지원했다. 이 외에도 long long int, _Bool 같은 새로운 자료형과 구조체 및 공용체의 유연한 초기화 문법(designated initializers)이 추가되었다.
표준 라이브러리 측면에서도 개선이 이루어졌다. 새로운 헤더 파일들이 도입되어 수학 함수의 정밀도 향상, 부동소수점 환경 제어, 정수형의 너비를 명시적으로 정의하는 타입(inttypes.h) 등을 제공하게 되었다. 이러한 변화는 C 언어가 임베디드 시스템과 고성능 계산과학 분야를 포함한 더 넓은 범위의 응용 분야에 적합하도록 만드는 데 기여했다.
그러나 C99는 모든 기능이 널리 채택되지는 못했다. 특히 가변 길이 배열과 복소수 지원은 일부 주요 컴파일러에서 제한적으로 구현되거나 후속 표준에서 선택적 기능으로 변경되기도 했다. 그럼에도 불구하고 C99는 C 언어의 발전에 있어 중요한 이정표였으며, 이후의 C11과 C17 표준의 기반을 마련했다.
2.4. ISO/IEC 9899:2011 (C11)
2.4. ISO/IEC 9899:2011 (C11)
ISO/IEC 9899:2011은 흔히 C11로 불리는 C 프로그래밍 언어의 국제 표준이다. 이 표준은 2007년부터 시작된 개정 작업의 결과물로, 2011년 12월에 공식적으로 발표되었다. C11은 이전 표준인 C99의 개정판으로, 새로운 기능을 추가하고 기존 기능을 명확히 하며, C++ 언어와의 호환성을 높이는 것을 주요 목표로 삼았다.
C11 표준은 다중 스레드 지원을 위한 표준 라이브러리(스레드) 확장을 핵심 기능으로 도입했다. 이는 <threads.h> 헤더 파일을 통해 동시성 프로그래밍을 위한 표준화된 인터페이스를 제공함으로써, 이전까지 컴파일러나 운영 체제에 의존적이었던 멀티스레딩 구현의 이식성을 크게 향상시켰다. 또한, 표준은 보안 강화를 위해 경계 검사 인터페이스(<bounds_checking.h>)와 같은 선택적 기능들을 정의했다.
이 표준은 호환성 유지를 중시하여, 대부분의 새로운 기능들은 매크로 __STDC_VERSION__의 값이 201112L로 정의되었을 때만 사용 가능하도록 규정했다. C11은 또한 C99에서 도입되었으나 널리 지원되지 않았던 몇 가지 기능(예: 가변 길이 배열)을 선택적 기능으로 전환하는 등 실용적인 조정을 가했다. 이를 통해 컴파일러 제작자와 개발자 모두에게 더 유연한 준수 모델을 제공하였다.
C11의 발표는 시스템 프로그래밍과 임베디드 시스템 분야에서 C 언어의 현대적 요구사항, 특히 안전성과 동시성에 대한 수요를 반영한 중요한 진전으로 평가된다. 이 표준은 GCC와 Clang을 비롯한 주요 컴파일러들에 의해 단계적으로 지원되기 시작했다.
2.5. ISO/IEC 9899:2018 (C17/C18)
2.5. ISO/IEC 9899:2018 (C17/C18)
ISO/IEC 9899:2018은 C 프로그래밍 언어의 2018년 개정판으로, 비공식적으로 C17 또는 C18로 불린다. 이 표준은 2011년에 발표된 C11 표준 이후의 첫 번째 개정판이며, 주로 기술적 오류를 수정하고 명확성을 높이는 데 초점을 맞췄다. 새로운 주요 기능을 추가하기보다는 기존 C11 표준의 결함 보고서를 해결하고 언어 명세를 다듬는 것이 목표였다.
이 표준은 C11의 필수 기능을 모두 포함하면서도, C11에서 선택 사항이었던 __STDC_NO_ATOMICS__, __STDC_NO_COMPLEX__, __STDC_NO_THREADS__, __STDC_NO_VLA__ 매크로에 대한 지원을 구현체가 제공하지 않을 경우 반드시 정의하도록 요구사항을 강화했다. 또한, C11의 Annex K(보안 체계)에 대한 지원은 여전히 선택 사항으로 남아 있으며, 많은 주요 컴파일러에서 이를 구현하지 않는다.
C17/C18은 C11과의 하위 호환성을 유지하며, C11을 지원하는 대부분의 코드는 수정 없이 컴파일될 수 있다. 이 개정판은 새로운 언어 기능을 도입하지 않았기 때문에, GCC나 Clang과 같은 주요 컴파일러는 비교적 빠르게 이 표준에 대한 지원을 완료했다. C17/C18의 발표는 C11 이후의 불안정한 요소를 정리하고, 다음 주요 개정판인 C23을 위한 안정적인 기반을 마련했다는 의의가 있다.
2.6. ISO/IEC 9899:2024 (C23)
2.6. ISO/IEC 9899:2024 (C23)
ISO/IEC 9899:2024는 C 프로그래밍 언어의 최신 국제 표준으로, 2024년에 공식적으로 발표되었다. 이 표준은 비공식적으로 C23이라고도 불리며, 이전 표준인 C17 이후 약 6년 만에 나온 주요 개정판이다. C23은 언어의 현대화와 결함 수정에 초점을 맞추어, 개발자들이 더 안전하고 효율적으로 코드를 작성할 수 있도록 여러 새로운 기능과 개선 사항을 도입했다.
주요 새로운 기능으로는 #elifdef 및 #elifndef 전처리기 지시자의 추가, nullptr 상수의 도입, constexpr 한정자의 지원, 그리고 typeof 및 typeof_unqual 연산자의 표준화가 포함된다. 또한, 표준 라이브러리 측면에서는 메모리 안전성을 강화하기 위한 memset_explicit() 함수와 같은 새로운 함수들이 추가되었으며, 유니코드 지원이 확대되어 char8_t, char16_t, char32_t와 관련된 라이브러리 기능이 보강되었다.
이 표준은 기존 코드의 호환성을 유지하면서도 언어를 발전시키는 데 중점을 두었다. 예를 들어, C++과의 호환성을 높이기 위한 기능들이 다수 채택되었으며, 이식성을 해치지 않는 선에서 구식 문법과 라이브러리 요소에 대한 사용 자제(deprecated) 표시가 추가되거나 제거되었다. C23은 시스템 프로그래밍과 임베디드 시스템 개발을 포함한 C 언어의 전통적인 강점 분야에서 여전히 중요한 역할을 할 것으로 기대된다.
3. 표준의 주요 내용
3. 표준의 주요 내용
3.1. 언어 문법과 구문
3.1. 언어 문법과 구문
ISO C 표준은 C 언어의 핵심 문법과 구문을 엄격히 정의하여, 서로 다른 컴파일러와 운영 체제에서도 일관된 동작을 보장하는 코드 작성의 기초를 제공한다. 이 표준은 변수 선언, 자료형, 연산자, 제어 흐름 문장, 함수 정의 및 호출 규약 등 언어의 기본 구조를 명시한다. 특히, 포인터 연산, 배열과 포인터의 관계, 구조체와 공용체의 메모리 배치 등 저수준 프로그래밍에 필수적인 개념에 대한 규칙을 포함한다.
표준은 언어의 구문을 BNF나 이와 유사한 형식 문법을 사용하여 공식적으로 기술한다. 이는 어휘 분석, 구문 분석, 의미 분석 단계를 거치는 컴파일러가 소스 코드를 해석하는 정확한 규칙을 제공한다. 예를 들어, 변수 스코프와 생명주기, 형 변환의 규칙, 기억 부류 지정자(auto, static, register, extern)의 의미 등이 상세히 정의되어 있다.
또한 표준은 다양한 문맥에서의 표현식 평가 순서와 같은 세부 사항을 규정하여, 프로그래머가 특정 하드웨어나 컴파일러 구현에 의존하지 않고 이식성 높은 코드를 작성할 수 있도록 돕는다. 전처리기 지시문(#include, #define, #ifdef 등)의 처리 방식도 표준의 일부로 포함되어, 조건부 컴파일과 매크로 확장이 예측 가능한 방식으로 이루어지도록 보장한다. 이러한 명확한 문법과 구문 정의는 C 언어가 시스템 프로그래밍과 임베디드 시스템 같은 신뢰성과 정확성이 요구되는 분야에서 널리 사용되는 근간이 된다.
3.2. 표준 라이브러리
3.2. 표준 라이브러리
ISO C 표준은 언어의 핵심 문법과 함께 광범위한 표준 라이브러리를 정의한다. 이 라이브러리는 헤더 파일의 형태로 제공되며, 입출력, 문자열 처리, 수학 함수, 메모리 관리, 시간 처리 등 프로그래밍에 필수적인 기능들을 포함한다. 표준 라이브러리의 존재는 이식성을 크게 향상시키는 데 기여한다. 즉, 표준에 명시된 함수와 헤더를 사용하여 작성된 코드는 서로 다른 컴파일러와 운영 체제에서도 동일한 방식으로 동작할 가능성이 높아진다.
표준 라이브러리는 크게 몇 가지 주요 카테고리로 나눌 수 있다. stdio.h는 파일 및 콘솔 입출력을 담당하는 printf, scanf, fopen 등의 함수를 제공한다. stdlib.h는 메모리 할당(malloc, free), 프로그램 종료(exit), 난수 생성 등의 유틸리티 함수를 포함한다. string.h는 문자열 조작 함수들을, math.h는 수학 연산 함수들을 정의한다. 또한 time.h는 시간 관련 함수를, assert.h는 디버깅을 위한 어서션 매크로를 제공한다.
이러한 표준 라이브러리의 명세는 각 표준화 버전마다 조금씩 진화해 왔다. 예를 들어, C99에서는 복소수 연산 지원과 새로운 수학 함수들이 추가되었으며, C11에서는 멀티스레딩 지원을 위한 threads.h 헤더가 도입되었다. 최신 표준인 C23에서는 더 많은 현대적 기능과 보안 강화 함수들이 라이브러리에 포함되었다. 이러한 지속적인 확장은 C 언어가 현대 프로그래밍 요구사항을 계속해서 충족할 수 있도록 돕는다.
표준 라이브러리의 구현은 각 컴파일러 벤더나 운영 체제 개발자의 몫이다. 예를 들어, GNU C 라이브러리(glibc)는 리눅스 시스템의 주요 구현체이며, 마이크로소프트는 비주얼 C++ 런타임 라이브러리(MSVCRT)를 제공한다. 이러한 구현체들은 모두 ISO C 표준이 요구하는 최소한의 기능을 제공해야 하지만, 벤더별로 추가적인 확장 기능이나 성능 최적화를 포함할 수 있다.
3.3. 이식성 보장
3.3. 이식성 보장
ISO C 표준은 다양한 하드웨어 플랫폼과 운영 체제 간에 C 언어로 작성된 프로그램의 이식성을 보장하는 것을 핵심 목표로 한다. 이식성 보장은 표준이 언어의 구문과 표준 라이브러리의 동작을 명확히 정의함으로써 달성된다. 표준은 특정 컴파일러나 하드웨어 아키텍처에 종속되지 않는 공통의 기반을 제공하여, 개발자가 하나의 소스 코드를 수정 없이 또는 최소한의 수정으로 다른 환경에서 컴파일하고 실행할 수 있게 한다.
이를 위해 표준은 정의된 동작과 구현 정의 동작, 미지정 동작, 미정의 동작을 엄격히 구분한다. 정의된 동작은 모든 표준을 준수하는 구현체에서 동일한 결과를 보장하는 반면, 구현 정의 동작은 각 구현체가 어떻게 동작할지 문서화해야 하는 사항이다. 예를 들어, 기본 데이터 타입의 크기나 바이트 순서는 구현 정의되어 있어, 이식성이 중요한 프로그램은 이러한 차이를 고려하여 작성되어야 한다.
표준 라이브러리의 함수 인터페이스와 동작을 표준화한 것도 이식성 보장에 크게 기여한다. 파일 입출력, 메모리 관리, 문자열 처리와 같은 핵심 기능들이 표준 헤더 파일을 통해 일관되게 제공된다. 따라서 개발자는 특정 벤더의 비표준 확장 기능에 의존하지 않고도 광범위한 시스템에서 동작하는 프로그램을 개발할 수 있다.
결과적으로, ISO C 표준은 시스템 프로그래밍부터 임베디드 시스템 개발에 이르기까지, 높은 이식성이 요구되는 분야에서 C 언어가 여전히 선호되는 근간이 된다. 이 표준 덕분에 리눅스 커널과 같은 복잡한 소프트웨어가 다양한 마이크로프로세서 아키텍처에서 동작할 수 있으며, 오픈 소스 생태계의 발전에도 기여했다.
3.4. 정의된 동작과 미정의 동작
3.4. 정의된 동작과 미정의 동작
ISO C 표준은 프로그램의 실행 결과를 예측 가능하게 하기 위해 정의된 동작을 명시한다. 정의된 동작은 표준이 그 의미와 결과를 완전히 규정한 동작으로, 모든 준수하는 컴파일러와 플랫폼에서 동일하게 작동해야 한다. 예를 들어, 정수 오버플로우가 발생하지 않는 범위 내의 산술 연산이나 표준 라이브러리 함수의 명세된 사용법은 정의된 동작에 속한다. 프로그래머는 정의된 동작만을 의존할 때 이식성이 보장된 코드를 작성할 수 있다.
반면, 미정의 동작은 표준이 어떠한 요구사항도 부과하지 않는 동작을 말한다. 미정의 동작이 발생했을 때의 결과는 전혀 예측할 수 없으며, 프로그램이 아무 값이나 산출하거나, 오류 없이 실행되거나, 심지어 충돌을 일으키는 것까지 모두 허용된다. 대표적인 예로는 초기화되지 않은 변수의 값 읽기, 널 포인터 역참조, 배열 범위를 벗어난 접근, 하나의 객체를 서로 다른 타입으로 접근하는 엄격한 앨리어싱 규칙 위반 등이 있다.
구현 정의 동작은 미정의 동작과 구별되는 개념으로, 각각의 구현체(예: 특정 컴파일러와 플랫폼)가 어떻게 동작할지를 선택하고 문서화해야 하는 동작이다. 예를 들어, 데이터 타입의 정확한 크기(바이트 수)나 비트 필드의 배치 방식, char 타입의 기본 부호 유무 등이 여기에 해당한다. 이 동작은 특정 환경 내에서는 일관적이지만, 다른 환경으로 옮겼을 때 다르게 동작할 수 있어 이식성을 고려할 때 주의가 필요하다.
이러한 구분은 C 언어가 다양한 하드웨어 아키텍처를 효율적으로 지원하기 위한 설계 철학에서 비롯된다. 미정의 동작을 허용함으로써 컴파일러는 최적화를 더 공격적으로 수행할 수 있으며, 특정 하드웨어에서 가장 효율적인 코드를 생성할 수 있는 유연성을 가진다. 따라서 안정적이고 이식성 높은 시스템 소프트웨어를 개발하려면 프로그래머는 미정의 동작을 유발할 수 있는 코드를 피하고, 구현 정의 동작에 대한 의존성을 최소화하는 것이 중요하다.
4. 다른 C 표준과의 관계
4. 다른 C 표준과의 관계
4.1. K&R C
4.1. K&R C
K&R C는 C 프로그래밍 언어의 초기 비공식 표준을 가리키는 용어이다. 이 명칭은 언어의 창시자인 데니스 리치와 브라이언 커니핸이 공동 집필한 교재 'The C Programming Language'의 첫 번째 판(1978년 출간)에서 유래했다. 이 책의 부록에 수록된 언어 정의는 당시 벨 연구소에서 사용되던 C 컴파일러의 동작을 사실상의 표준으로 정립했으며, 이후 ANSI C와 ISO C가 공식 표준으로 제정되기 전까지 널리 참조되는 기준이 되었다.
K&R C는 현대적인 C 표준과 비교하여 문법과 기능 면에서 상당한 차이를 보인다. 예를 들어, 함수의 매개변수 선언 방식이 현대적인 프로토타입 선언과 달랐으며, 자료형 체계가 덜 엄격했다. 또한 오늘날 표준 C 표준 라이브러리의 핵심 요소인 많은 함수들이 아직 정의되지 않거나 초기 형태로만 존재했다. 이러한 특징으로 인해 K&R C로 작성된 코드는 최신 컴파일러에서 별도의 호환성 설정 없이는 컴파일되지 않을 수 있다.
공식 ISO/IEC 9899 표준이 제정된 이후, K&R C는 역사적인 의미를 가지게 되었다. 이는 프로그래밍 언어 표준화 과정의 중요한 초기 단계를 보여주며, C 언어의 설계 철학과 기본 골격이 이 시기에 확립되었음을 의미한다. 오늘날 대부분의 개발 환경은 ANSI C나 이후의 ISO 표준을 따르지만, 레거시 시스템 유지보수나 역사 연구 차원에서 K&R C에 대한 이해는 여전히 가치를 지닌다.
4.2. ANSI C와 ISO C의 동등성
4.2. ANSI C와 ISO C의 동등성
ANSI C와 ISO C는 본질적으로 동일한 표준을 가리킨다. 1989년 미국 국립 표준 협회(ANSI)가 제정한 C 언어 표준인 ANSI X3.159-1989는 1990년 국제 표준화 기구(ISO)와 국제 전기 표준 회의(IEC)에 의해 국제 표준으로 채택되었다. 이 국제 표준의 공식 명칭은 ISO/IEC 9899:1990이다. 따라서 기술적 내용상 ANSI C와 ISO C는 완전히 동등하며, 이 표준은 흔히 C89 또는 C90으로 불린다.
두 기관 간의 협력 관계로 인해 이후의 표준 개정도 유사한 과정을 거친다. ANSI가 표준을 갱신하면 ISO/IEC가 이를 국제 표준으로 채택하는 방식이었다. 예를 들어, 1999년에 제정된 주요 개정판은 ANSI에서는 "ANSI X3.159-1989의 수정"으로, 국제적으로는 ISO/IEC 9899:1999(C99)으로 출판되었다. 이로 인해 시장에서는 ANSI C와 ISO C라는 용어가 혼용되어 왔으며, 둘 다 공식적인 C 언어 표준을 의미하는 것으로 이해된다.
현재는 ISO/IEC JTC 1/SC 22(프로그래밍 언어, 그 환경 및 시스템 소프트웨어 인터페이스 분과위원회) 산하의 WG14(C 언어 작업 그룹)이 표준 개발의 주도적 역할을 담당하고 있다. ANSI는 이 작업 그룹에 미국 대표로 참여하여 표준화 과정에 기여한다. 따라서 최신 표준인 C23(ISO/IEC 9899:2024)은 본질적으로 하나의 국제 표준이며, 이를 ANSI가 자국의 표준으로 수용하는 구조이다.
4.3. GNU C 확장 (GCC)
4.3. GNU C 확장 (GCC)
GNU C 확장은 GNU 컴파일러 모음(GCC)이 ISO C 표준을 확장하여 제공하는 기능들이다. 이 확장들은 주로 저수준 시스템 프로그래밍이나 성능 최적화를 위해 설계되었으며, 표준 C만으로는 표현하기 어렵거나 불가능한 특정 작업을 수행할 수 있게 한다. 이러한 확장 기능을 사용하면 특정 하드웨어 플랫폼이나 운영 체제에 더 밀접하게 접근하거나 컴파일러에게 최적화 힌트를 제공하는 등 다양한 이점을 얻을 수 있다. 그러나 확장 기능에 의존하는 코드는 이식성이 떨어질 수 있어, 표준 준수와 확장 사용 사이의 균형을 고려해야 한다.
주요 GNU C 확장에는 인라인 어셈블리(인라인 어셈블리) 삽입, 변수 속성 지정, 함수 속성 지정, 문장 표현식, 가변 길이 배열의 확장된 사용, 타입 제네릭 표현식 등이 포함된다. 예를 들어, __attribute__ 키워드를 사용하여 변수의 정렬 방식을 지정하거나, 함수가 순수 함수임을 컴파일러에 알려 최적화를 유도할 수 있다. 또한, __builtin_ 접두사가 붙은 내장 함수들을 통해 CPU의 특수 명령어를 직접 호출하거나, 컴파일 타임에 상수 폴딩과 같은 작업을 수행할 수 있다.
이러한 확장들은 리눅스 커널 및 GNU 프로젝트의 핵심 도구들을 포함한 많은 자유 소프트웨어와 오픈 소스 소프트웨어에서 광범위하게 사용된다. 개발자는 일반적으로 전처리기 매크로(예: __GNUC__)를 사용하여 GCC 컴파일러를 감지하고, 확장 기능의 사용을 조건부로 컴파일하여 다른 컴파일러에서의 호환성을 유지한다. GNU C 확장의 사용은 코드의 성능과 기능성을 극대화하는 동시에, 표준 C 코드 베이스를 유지해야 하는 경우에는 신중하게 관리되어야 한다.
5. 준수와 구현
5. 준수와 구현
5.1. 호환성 수준
5.1. 호환성 수준
ISO C 표준을 준수하는 컴파일러는 특정 표준 버전에 대한 호환성 수준을 설정할 수 있다. 이는 코드가 특정 표준(예: C89, C99, C11)에 맞춰 작성되었음을 컴파일러에 알려주고, 해당 표준의 규칙에 따라 코드를 검증하고 컴파일하도록 지시한다. 호환성 수준을 명시적으로 설정함으로써, 개발자는 새로운 표준 버전의 컴파일러가 이전 버전의 코드를 잘못 해석하거나 오류를 발생시키는 것을 방지할 수 있다.
주요 컴파일러들은 명령줄 옵션을 통해 이러한 호환성 수준을 지정한다. 예를 들어, GCC는 -std=c99나 -std=c11과 같은 옵션을 제공하며, Microsoft Visual C++ 컴파일러는 /std:c11 등의 옵션을 지원한다. 이러한 설정은 언어 확장을 허용할지 여부도 결정할 수 있는데, GNU 확장을 포함하는 -std=gnu99 모드와 순수 ISO C만을 따르는 -std=c99 모드가 그 예이다.
호환성 수준 설정은 이식성을 보장하는 데 핵심적이다. 특정 표준 버전에 맞춰 코드를 작성하고 컴파일하면, 다른 플랫폼이나 다른 벤더의 컴파일러에서도 동일한 동작을 기대할 수 있는 가능성이 높아진다. 이는 특히 크로스 플랫폼 소프트웨어나 임베디드 시스템과 같이 다양한 환경에서 실행되어야 하는 프로젝트에서 중요하다.
표준 준수 모드는 또한 코드의 미래 보장성과도 관련이 있다. 최신 표준 모드로 컴파일하면 새로운 언어 기능과 표준 라이브러리 개선 사항을 활용할 수 있지만, 오래된 환경에서는 지원되지 않을 수 있다. 반면, 오래된 표준 모드를 고수하면 광범위한 호환성을 얻는 대신 최신 언어의 편의성과 안전성 기능을 사용하지 못할 수 있다. 따라서 프로젝트의 요구사항과 목표 플랫폼을 고려하여 적절한 호환성 수준을 선택하는 것이 중요하다.
5.2. 주요 컴파일러의 지원 현황
5.2. 주요 컴파일러의 지원 현황
주요 C 컴파일러들은 각각 다른 수준으로 ISO C 표준을 지원한다. GCC와 Clang은 현대적인 표준에 대한 지원이 가장 활발한 편이다. GCC는 -std=c11, -std=c17, -std=c2x와 같은 옵션을 통해 특정 ISO C 표준을 준수하는 모드로 컴파일할 수 있으며, Clang도 유사한 옵션을 제공한다.
마이크로소프트의 MSVC는 전통적으로 C++에 비해 C 표준 지원에 소극적이었으나, 최근 버전에서는 C11과 C17 표준의 상당 부분을 지원하기 시작했다. 다만, 스레드 관련 헤더 등 일부 기능은 여전히 제한적이다. 임베디드 시스템 분야에서 널리 사용되는 IAR, KEIL, Green Hills 등의 컴파일러는 주로 대상 하드웨어와 시장 요구에 맞춰 특정 표준 버전을 선택적으로 지원한다.
컴파일러마다 지원하는 표준 버전과 호환성 수준이 다르므로, 코드의 이식성을 높이려면 특정 컴파일러의 확장 기능을 사용하기보다는 표준에 정의된 기능만을 사용하는 것이 권장된다. 또한, 대부분의 컴파일러는 표준 준수 모드 외에도 기본적으로 자체 확장 기능을 활성화하는 모드를 제공하며, 이는 표준과의 호환성을 떨어뜨릴 수 있다.
6. 의의와 영향
6. 의의와 영향
ISO C는 C 프로그래밍 언어의 공식적인 국제 표준으로서, 언어의 명세를 통일하고 이식성을 보장하는 데 결정적인 역할을 했다. 이 표준이 제정되기 전에는 데니스 리치와 브라이언 커니핸이 제안한 K&R C와 같은 사실상의 표준이 존재했으나, 컴파일러마다 세부 구현이 달라 호환성 문제가 빈번했다. ISO C의 등장은 이러한 파편화를 해소하고, 서로 다른 하드웨어 플랫폼과 컴파일러에서도 동일한 동작을 기대할 수 있는 견고한 기반을 마련했다. 이는 특히 운영 체제와 임베디드 시스템 같이 하드웨어와 밀접하게 연관된 시스템 프로그래밍 분야에서 소프트웨어의 이식성과 신뢰성을 크게 향상시켰다.
ISO C의 영향은 프로그래밍 언어 자체를 넘어 전산학 전반에 걸쳐 있다. 이 표준은 후속 주요 프로그래밍 언어들의 설계에 지대한 영향을 미쳤으며, C++, Objective-C, C#, 자바, Go 등은 모두 문법적 기반이나 개념적 측면에서 C 언어의 유산을 이어받았다. 또한, 표준이 명확히 정의한 메모리 모델, 데이터 타입, 표준 라이브러리의 규격은 수많은 응용 소프트웨어와 교육 커리큘럼의 기초가 되었다. 현대 컴퓨팅의 핵심을 이루는 대부분의 커널과 런타임 라이브러리는 C 언어로 작성되었으며, 이들의 구현은 ISO C 표준을 준수함으로써 광범위한 생태계를 구축할 수 있었다.
표준의 지속적인 개정은 언어가 현대 프로그래밍의 요구사항을 따라갈 수 있도록 했다. C99는 인라인 함수와 가변 길이 배열 등을 도입했고, C11은 다중 스레드 지원과 경계 검사 함수를 표준화하며 언어의 진화를 이끌었다. 최근의 C23 표준은 현대 하드웨어 아키텍처와 보안 강화 요구에 대응하는 기능을 추가하고 있다. 이러한 진화 과정은 ISO C가 단순한 레거시 언어가 아닌, 여전히 고성능 컴퓨팅과 저수준 프로그래밍 분야에서 필수적인 도구로 자리매김하도록 했다. 결과적으로, ISO C는 프로그래밍 언어 역사상 가장 성공적이고 영향력 있는 표준 중 하나로 평가받으며, 컴퓨터 과학의 발전에 지속적으로 기여하고 있다.
