K&R C, 우리가 몰랐던 문법의 비밀
K&R C와 C89 표준 이전의 문법적 모호성(Grammatical Ambiguity)과 단일 패스 컴파일러(Single-Pass Compiler)의 역사적 맥락을 탐구함.
void 타입 부재, long float vs double, 제한된 타입 명시자 조합 등 초기 C의 독특한 특징을 발견함.
정수 승격(Integer Promotion) 규칙의 값 보존(Value Preserving) 대 부호 없는 값 보존(Unsigned Preserving) 방식의 차이와 표준화 과정을 조명함.
문자열 리터럴의 가변성(Mutable String Literals), 함수 파라미터 타입 조정 부재 등 표준 C와 다른 K&R C의 동작 방식을 분석함.
K&R C의 문법적 모호성과 단일 패스 컴파일러
초기 C 언어의 문법적 모호성, 특히 typedef와 식별자(Identifier)의 문맥 의존성은 단일 패스 컴파일러(Single-Pass Compiler) 설계의 필요성에서 비롯되었다는 분석이 제시됨. 메모리 제약이 심했던 환경에서 컴파일러는 스코프와 식별자를 파싱 중에 추적해야 했으며, 이는 문법 변경을 비교적 쉽게 처리할 수 있게 했다고 설명함. 현대 C의 복잡한 스코핑 규칙과 달리 K&R C에서는 이러한 문맥 민감성이 큰 문제가 되지 않았다고 언급됨.
초기 C 언어의 타입 시스템 특징
K&R C에는 void 타입이 없었으며, 함수는 암묵적으로 `int`를 반환했음. 또한, 모든 포인터 타입이 서로 호환되었고, long float이 `double`의 동의어로 사용되는 등 현대 C와 다른 타입 명시자(Type Specifier) 규칙이 존재했음. `unsigned`는 `int`와 함께 사용될 때만 유효했으며, `unsigned short int`와 같은 조합은 확장 기능으로 나중에 도입되었음을 지적함.
정수 승격(Integer Promotion) 규칙의 역사적 변화
K&R C의 `unsigned` 타입 관련 정수 승격(Integer Promotion) 규칙은 '값 보존(Value Preserving)'과 '부호 없는 값 보존(Unsigned Preserving)' 두 가지 방식으로 나뉘었음. C89 표준은 '값 보존' 방식을 채택했는데, 이는 부호 없는 정수와 부호 있는 정수 간의 충돌을 최소화하여 프로그래머에게 더 안전한 경험을 제공하기 위함이었다고 설명함. 이는 당시 Unix C 컴파일러들이 주로 사용하던 방식과 상반되는 결정이었음을 흥미롭게 지적함.
문자열 리터럴과 타입 qualifiers의 관계
K&R C에서 문자열 리터럴(String Literals)은 가변 객체(Mutable Objects)로 취급되었으며, 이는 `char *` 타입으로 반환되는 이유임. ANSI C에서 `const` 타입 qualifier가 도입되었음에도 불구하고, 기존 코드와의 호환성을 위해 문자열 리터럴은 불변(Immutable)으로 간주되면서도 `const`를 사용하지 않게 되었다는 점을 분석함. 이는 타입 qualifiers 도입 시 호환성 문제를 보여주는 사례로 언급됨.
전처리기(Preprocessor) 기능의 제약과 발전
K&R C에는 `#pragma`, `#error`, `#elif`와 같은 전처리기 지시자(Preprocessor Directives)가 없었으며, 매크로 문자열화(`stringizing`, `#`) 및 붙이기(`pasting`, `##`) 연산자도 ANSI 표준에서 도입되었음. 매크로 내 문자열 리터럴 확장은 많은 구현에서 지원되었으나, 표준화되지 않은 상태였음을 지적함. 또한, `__DATE__`, `__FILE__`과 같은 미리 정의된 매크로(Predefined Macros)도 존재하지 않았다고 설명함.
구조체(Struct) 및 공용체(Union)의 초기 제약
초기 C 언어에서는 구조체(Struct) 및 공용체(Union)의 할당(Assignment) 및 반환(Return)이 불가능했으며, 초기화 시에도 제약이 많았음. 특히 자동 변수(Stack-allocated) 구조체나 공용체는 필드별로 개별 할당해야 했음. 이는 현대 C에서 구조체와 공용체를 값으로 다루는 것과 큰 차이를 보이며, 데이터 구조 처리의 복잡성을 증가시켰다고 분석함.