[include(틀:프로그래밍 언어)] [include(틀:TIOBE/C)] ||<-2> '''{{{+3 C}}}''' || ||<-2> [[파일:C언어 로고.svg|width=200]] || || '''개발''' ||국제 표준화 기구([[ISO]]) || || '''버전''' ||{{{+1 '''18'''}}}^^(2018년 6월 업데이트)^^ || || '''웹사이트''' ||[[https://en.cppreference.com/w/|홈페이지]] || [목차] [clearfix] == 개요 == {{{#!syntax cpp #include int main(int argc, char** argv) { printf("Hello world"); } }}} [* 'int argc, char** argv' 부분을 'void' 또는 빈 칸으로 대체하는 경우도 있으며, char** argv는 char *argv\[\]로 대체할 수 있다. 또한 C언어 버전이 C11 이상이라면 int main()이라고 써도 된다. 아무거나 써도 시스템에 문제가 가거나 딱히 달라지는 건 없으니까 쓰고 싶은 거 쓰자. (main함수의 반환값은 반드시 int여야 한다. 이외에는 표준이 아닌 Undefined Behaviour이다. ISO/IEC 9899:201x § 5.1.2.2.3 Program termination)] [* C99부터 main 함수에 한정해서 return 0;은 있어도 되고 없어도 된다. 정확히는 main 함수에 한정해서 return 문이 없는 경우 return 0;이 자동으로 붙는다.] [* main 함수는 단순히 링커가 main 함수 심볼의 주소를 바이너리의 엔트리 포인트로 지정해 주는 것에 불과하기에 main이 아닌 다른 함수를 프로세스의 진입 지점으로 변경하는 것이 가능하다. 대표적으로 GCC의 [[https://gcc.gnu.org/onlinedocs/gcc/Link-Options.html#:~:text=-e%20entry,or%20an%20address.|링커 옵션인 {{{--entry}}}플래그.]]] > The computing world has undergone a revolution since the publication of The C Programming Language in 1978. > 1978년 책 "The C Programming Language" 출판 이후 컴퓨팅 세계는 혁명을 겪어왔다. >---- > - The C Programming Language 2nd Edition [* [[데니스 리치]]와 브라이언 커니핸 지음. [[http://cs.indstate.edu/~cbasavaraj/cs559/the_c_programming_language_2.pdf|#]]] [[1972년]]에 벨 연구소(Bell Labs)의 [[데니스 리치]][* 켄 톰슨과 브라이언 커니헨은 발전과정에 기여했을 뿐 공동개발자가 아니다. 켄 톰슨은 유닉스 OS와 C언어의 전신인 B언어를 만들었고, 브라이언 커니핸은 K&R로 불리는 The C Programming Language라는 C언어의 역사에 중요한 책을 썼다.]가 만든 범용(general-purpose) [[프로그래밍 언어]]. 원래 명칭은 그냥 'C'지만 한국에서는 표제어에서도 볼 수 있듯 'C언어'라는 명칭으로 주로 부른다. 영미권에서도 Clang이라고 부르는 사례가 있다. 세계적으로 많이 쓰이는 [[프로그래밍 언어]] 중 하나이다. 온라인 상으로 코드를 실행시켜 보고 싶다면 [[https://repl.it/languages/c|여기]]로. == 설명 == C언어의 정신은 C99 Rationale에서 다음과 같이 묘사하고 있다. * '''프로그래머를 믿어라. (Trust the programmer)''' * 프로그래머가 작업을 못하게 방해하지 마라. (Don't prevent the programmer from doing what needs to be done) * 언어를 작고 간단하게 유지하라. (Keep the language small and simple) * 명령을 실행하는 방법을 하나만 제공하라. (Provide only one way to do an operation) * 호환성은 장담할 수 없더라도 빨리 작동하게 만들어라. (Make it fast, even if it is not guaranteed to be portable) 첫 줄의 ''''프로그래머를 믿어라'''' 부분이 오늘날 다른 언어들과 가장 큰 차이를 불러오는 것이다. 오늘날 다른 고생산성 언어들이 프로그래머를 못 믿고 퍼포먼스 희생을 감수하고서라도 문제가 생길만한 부분들을 컴파일러 또는 가상 머신에서 자동으로 처리해주거나 [[Rust(프로그래밍 언어)|프로그래머가 이상한 코드를 짜지 못하도록 엄격하게 컴파일]]해준다면, C언어는 "프로그래머인 당신을 믿을 테니까 '''알아서 프로그래밍해라'''." 한마디로 끝낸다.[* 좋게 말하면 프로그래밍 스크립트 제작에 제한이 거의 없다는 뜻이 되지만, 다르게 말하면 에러나 버그 등의 문제를 프로그래머 스스로가 직접 일일이 찾아내야만 한다는 얘기다.] C언어 자체는 지원되는 기능이 적고 문법이 간단하다. [[객체 지향 프로그래밍]](OOP)이나 코루틴, 클로저, 메타 프로그래밍 등 고수준의 기능들을 지원하는 언어들과 비교하면 특히나 그렇다. 550쪽 정도밖에 안 되는 C언어 표준에서도 순수 문법 부분은 200쪽 정도밖에 안 되며 나머지는 다 라이브러리 관련 부분이고, 함수의 개수로 치면 고작해야 150개 근처이다. 수천 개나 되는 기본 라이브러리를 지원하는 다른 언어들과 비교하면 정말 작고 간단하다. 초반의 포인터 장벽만 넘는다면 문법 자체를 마스터하고 간단한 커맨드라인 프로그래밍을 할 수 있는 수준까지는 엄청 쉽다. 하지만 기능이 적다고 결코 쉬운 건 아니다. 프로그래밍을 할 때 지원하는 기능이 적다고 그 적은 기능만 쓸 수는 없다. 따라서 기본 라이브러리에서 지원하지 않는 기능은 결국 프로그래머가 직접 구현해서 써야 하는데, 1970년대 이후 프로그래밍 언어계에서 오늘날 영어와 같은 위치를 차지하고 있던 덕분에 그런 기능의 구현이나 최적화에 관한 많은 트릭들이 존재하고 이것을 얼마나 많이 알고 있는 가가 사실 C언어의 핵심이다. 오늘날 고수준 언어들이 다수의 프로그래머가 함께 개발하는 것을 염두에 두고 팀에 누가 될 만한 위험하거나 생산성에 저해되는 부분들을 언어 차원에서 강제로 제외시키는 경향이 있다면, C언어는 이런 부분을 완전히 개방했다. 초기 C언어는 커다란 규모의 프로그램을 거의 염두에 두지 않고 개발됐다. 당시 IBM 메인 프레임에 사용되던 System/360이 수천 명의 프로그래머가 달라붙어 어셈블리어로 수백 만 줄이었는데, C언어로 만들어진 가장 큰 프로그램인 초창기 유닉스의 커널은 고작 만 줄 정도였다. 상황이 이렇다 보니 같은 프로그램이라도 프로그래머의 지식 수준과 능력에 따라 퀄리티 차이가 그야말로 극과 극으로 벌어지는 언어이다. [[Linux|리눅스]] 등 C언어로 작성된 대규모 오픈소스 프로젝트를 보면 C언어 활용의 예술을 볼 수 있다. 방대한 양의 코드를 함수, 구조체, 포인터, 매크로만을 이용해서 철저히 모듈 단위로 잘 관리하고 있다. 어떤 언어든 그 실력을 충분히 발휘하려면 주로 쓰이는 분야에서 사용하게 되는 기술을 익혀야 하는데, C언어의 주 사용 분야라는 것이 하필 '''기계 제어'''. 제대로 사용하려면 프로그래머들이 보통 싫어하는 하드웨어와 어셈블리어에도 결국 손을 대야 한다. 일반적인 프로그래밍도 역시 가능하지만, 그런 용도로는 더 적합한 언어들이 널려 있다. 2010년대부터는 데스크톱 애플리케이션보다 웹, 스마트폰 애플리케이션의 활용도가 높아져서, 하드웨어 컨트롤이나 성능이 중요한 분야[* 단순히 고성능 라이브러리를 가져다 쓰는 게 아닌 고성능이 필요한 라이브러리 그 자체]가 아니면 C언어를 써야 할 이유가 거의 없다. 즉, 초심자가 C언어를 배우는 것까지는 문제가 없지만 배우고 나서 뭔가 제대로 할만한 건 사실상 없다. 그리고, 바로 그렇기 때문에 프로그래밍 입문용 언어의 자리도 해외 기준으로는 대부분 [[Java]]나 [[Python]]으로 대체됐다. 또한 데스크톱 애플리케이션도 [[HTML]]/[[CSS]]/[[JavaScript]]를 이용하는 Electron 프레임워크가 나오면서 예전보다 개발이 훨씬 쉬워졌다.[* 현재 Electron은 [[마이크로소프트]]에게 인수됐으며, [[스카이프]]와 [[Visual Studio Code]]의 개발에 요긴하게 사용됐다.] === 사용 분야 === C언어는 다음과 같은 분야에서 사용되며, 일반 사용자의 눈에 보이지 않는 컴퓨터 산업의 기반이 되는 곳에서 주로 쓰인다. * [[운영체제]][* [[Microsoft Windows|윈도우]], [[Linux|리눅스]], [[유닉스]] [[커널(운영 체제)|커널]]의 핵심부는 모두 C언어로 짜여 있다.][* 리눅스 외의 커널에서는 C++도 사용되곤 한다.] 및 디바이스 드라이버 * [[마이크로컨트롤러]] * [[임베디드 시스템]] * [[암호학]] 라이브러리[* 비트 수준 연산을 많이 사용하고, 속도도 빨라야 한다.] * 프로그래밍 언어 인터프리터([[Python|CPython]] 등) * 웹 서버([[Apache]] 등) * [[데이터베이스]]([[PostgreSQL]] 등) * [[애플리케이션]] * 이외에 매우 빠른 계산 속도가 필요한 프로그램이나 라이브러리[* 특히나 [[양자역학]] 등 과학 계산 용도. 쓸모 있는 데이터 하나를 얻기 위해 엄청난 연산량을 요구하는 이런 분야에서는 계산 하나하나의 사소한 퍼포먼스 저하가 연구 성과를 심하면 문자 그대로 몇 년씩 늦추므로 극한의 퍼포먼스가 필요하다.] === 등장 배경 === C언어 이전에도 고수준 언어들은 많이 존재했지만, 대부분 특정 애플리케이션 영역을 대상으로 하거나, 컴퓨터 과학 이론을 입증하기 위해 만들어진 실험실 언어들이었다. 어플리케이션 영역이 아닌 운영체제를 어셈블리어가 아닌 언어로 작성한다는 것은 당시엔 금기였다. 유닉스의 전신인 [[멀틱스|MULTICS]]는 그 금기를 어기고 PL/1라는 고수준 언어로 작성하려고 시도했으나, 불운하게도 성공하지 못했다. 유닉스는 멀틱스에 대한 반성에서 단순하게 만드는 방향을 추구했으며, 그렇기에 이름부터가 UNI-로 시작하도록 지었다. C언어와 유닉스는 소수의 예외를 제외하고 대부분을 C언어로 작성하고서도 우려와는 달리 단점보다 장점이 훨씬 많다는 것을 보이면서 이 금기에 정면으로 도전해서 승리했다.[* 유닉스는 처음에는 어셈블리어로 만들어졌지만 점차 C언어로 대체됐다. 그리고 그 덕분에 이식성을 확보하여 여러 기계로 퍼져나갔다.] 그리고 지금은 운영체제는 C언어가 아니면 안된다는 새로운 금기가 생겼다. 실질적으로 성능과 효율성을 희생하지 않으면서도 수많은 플랫폼에서의 이식성을 제공하는 언어가 C언어 외에 그리 마땅치가 않기 때문이다. C언어가 등장하던 당시에는 [[코볼]], [[포트란]] 등이 고수준 언어로써 주로 쓰였는데, 이들은 [[천공 카드]]가 쓰이던 시절 만들어져서 문법이 매우 불친절하다.[* 천공 카드의 잔재로는 제일 왼쪽 몇 칸은 주석, 그 다음 몇 칸은 정의하는 식으로 코딩할 때 칸까지 맞추어야 하는 규칙이 있다. 당시 프로그래밍 자료를 보면 요즘 사람들의 눈에는 모눈 원고지로밖에 보이지 않을 것이다.][* 그리고 코볼은 원래는 프로그램 코드가 업무 서류로도 사용이 가능하도록(!) 설계가 되어 있어서 그렇다. 주석이 코드고 코드가 주석일 경우의 아주 나쁜 사례. 2000년대에 애자일 프로그래밍에서 코드를 쉽게 읽을 수 있게 한다는 개념과는 다르다. 이쪽은 추상화로 마치 자연어처럼 읽히는 코드를 써서 주석 자체를 코드로 최대한 대체해서 주석이 코드의 변화를 못 따라가는 불상사를 방지하는 것이다.] C언어는 이런 당대 고수준 언어들에 비해 매우 이해가 가기 쉬운 문법을 사용하여 초보자가 쉽게 접근할 수 있었다. === 장점 === C언어로 짜여진 코드는 속도가 빠르고 바이너리 크기도 작아 속도가 다른 무엇보다 (심지어는 생산성보다도) 중요한 임베디드 혹은 모바일 계열, 또는 시스템 프로그래밍 등에서 주로 쓰인다. Python등의 다른 언어들에 비해 기본으로 포함되는 크기도 작을 뿐더러 같은 알고리즘으로 짜도 결과물의 크기가 더 작은 경향이 있다. 과거에는 메모리 가격이 비쌌던 만큼 메모리를 적게 잡아먹는 프로그래밍 기법을 선호했으며, 화성 탐사선도 이러한 점을 반영하여 C언어로 만든 프로그램을 사용했다. 이러저러한 고급 언어들이 나오는 상황에서도 아직 저수준의 제어를 위해 C언어가 필요한 경우도 많다. 예를 들어, OS를 만든다면 아무리 생산성을 고려한다고 해도 시스템 제어 측면과 OS의 기능 위에서 돌아가는 애플리케이션 때문에라도 속도라는 면은 중요하고[* 쉽게 말해서, OS의 특정 기능이 느리면 그 기능을 사용하는 애플리케이션 전부가 덩달아 느려진다.], 그렇다고 속도를 높이기 위해 어셈블리어나 기계어로만 OS를 짜기에는 생산성이 매우 낮아지니, 타협점으로 C언어를 쓴다. 물론 시스템 콜 인터페이스나 ABI, 인터럽트, 부트 스트랩, 드라이버 등 머신에 직결된 부분에는 어셈블리나 기계어를 사용해야 한다. 아니면 머신 제조업체가 제공하는 라이브러리를 사용하거나. 최근 C언어/C++ 수준의 기계 제어와 안전한 메모리 관리를 동시에 제공하는 [[러스트(프로그래밍 언어)|Rust]]라는 언어가 새로 나오기는 했지만[* unsafe 콘텍스트로 C언어가 할 수 있는 모든 것을 동일한 성능으로 할 수 있다.], C언어와 C++는 원체 레거시가 오랫동안 유지되는 성향이 강해서 Rust가 메이저로 부상하기는 쉽지 않은 상황이다. 또한 대부분의 운영체제가 제공하는 [[API]]/시스템 콜은 C언어 기반이므로, 이를 직접 사용하려면 어찌되건 C언어를 래핑하는 방식으로밖에 쓸 수 없다. 그 외에 임베디드 시스템에서 단가 문제로 시스템 처리 능력과 메모리 제한이 매우 심각한 경우가 많은데, 이 경우도 C언어가 그나마 적합하다. 옛 시절 어셈블리어가 차지했던 자리를 현재는 C언어가 차지하고 있다고 봐도 된다. 이렇게 활용되는 부분이 많으므로 당분간 C언어가 사장될 가능성은 없다. 게다가 막대한 분량의 레거시 코드도 있고. 실제로 프로그래밍 언어 점유율 조사에서 한때 자바를 제치고 1위를 차지한 적도 있는 것을 보아서는 당분간 현역으로 왕성하게 활동할 것으로 보인다. 물론 이건 C언어의 점유율이 늘어났다기보다는 타 현대적인 언어들 덕분에 자바의 점유율이 줄어든 것이지만.[* 하지만 2020년 5월 기준 C언어가 다시 자바를 누르고 1위를 차지했는데, C언어가 최근 1년간 점유율이 2.82%나 증가해서 나온 결과다.] 안정성보다는 퍼포먼스를 골수까지 극한으로 뽑아내야 하는 게임 프로그래밍 분야 또한 C언어/C++가 대세. 게임 프로그래머들이 C언어에서 C++로 넘어가기를 끝까지 싫어했던 것은 오로지 C언어(지금은 C++)가 다른 언어보다 속도를 빠르게 최적화할 수 있다는 생각 때문이며, 그래서 다른 분야보다 보수적이라는 소리를 듣는 편이다. 그러나 요즘에는 [[모바일 게임]] 시장이 급속하게 커지면서, 코어 부분만 C언어/C++로 만들고 그 외의 상당 부분은 [[Python]], [[Java]], [[C\#]] 등의 고생산성 언어로 대체하는 경우가 늘어나고 있다. 현 시점에서 가장 중요한 장점 중 하나는 사실상 모든 아키텍처와 운영체제에서 가상머신 등의 추가적인 단계 없이 네이티브로 지원하는 언어라는 것이다. 그 다음으로 널리 쓰이는 C++조차도 이 정도로 지원되지는 않는다. 워낙 널리 쓰이다 보니 CPU 디자이너들이 가장 먼저 하는 일은 C언어를 instruction set으로 포팅하는 것일 정도다. 심지어 C언어 설계 자체가 CPU 인스트럭션 설계에 영향을 주는 단계에 이르렀다. 그런 관계로 이식성이 중요한 경우는 대개 C언어를 사용한다. 자바의 멀티플랫폼과는 성격이 다르다. 자바는 각 플랫폼용으로 만들어진 가상머신 위에서 같은 소스가 실행되는 것이고, C언어는 각 시스템에 맞는 기계어로 컴파일되는 것이다. 위에도 언급했던 자바 가상머신 자체가 C언어로 만들어져 있으므로 당연히 자바보다 범위가 넓다. 기존 C언어 프로그래머들은 진정한 멀티 플랫폼 언어는 자바가 아니라 C언어라고 믿는 사람도 부지기수. 표준을 고려하여 주의깊게 작성된 C언어 코드는 C언어 컴파일러가 있는 어떤 플랫폼에서도 최소한의 노력만으로 컴파일 - 실행이 가능하다.[* 다만, C언어 표준 자체가 많은 부분을 '모든 컴파일러에 동일하게'가 아니라 구현체에 따라(implementation-dependent) 정의하게 하므로 이런 부분들에 대해서는 전부 각 플랫폼마다의 특성을 따로 반영하여 코딩해주어야 한다.] 그게 쉽지 않아서 문제지. 요즘 C언어를 사용하는 이유는 위에도 쓰여 있듯이 저수준 제어인데, 이는 플랫폼에서 제공하는 API를 사용하지 않고는 불가능하다. 이런 특성상 런타임의 관점에서 보면 Rust, Python, Java, C++ 등의 사실상 거의 모든 언어의 런타임들부터가 C언어 런타임에 의존하고 있다. 이미 한물 간 언어처럼 보이지만, 여전히 '프로그래밍' 입문으로 C언어를 추천하는 사람이 많다. C언어라는 언어는 매우 심플하면서도 배우는 과정에서 소프트웨어 구성의 최소 단위인 비트부터 시작해서 메모리 관리, 그리고 고급 개념인 OOP 비스무리한 것까지[* 실제로 요즘 나오는 C언어 교재 중에는 후반부에 OOP 챕터도 넣어 놓은 경우가 가끔 있다.] 흉내내면서 소프트웨어 전반을 훑게 되고, C언어를 배우면서 나오는 과제들은 커맨드 라인에서 이미 쓰이고 있는 기본적인 툴을 'reinvent the wheel'[* 직역하면 '바퀴의 재발명'이다. 이미 다 존재해서 가져다 쓰기만 하면 되는 것을 괜히 고민하면서 또 만들어내는 것을 비판하는 데 쓰이는 문구이다. 다만 실전 개발에서 안 좋은 습성이고, 교육용으로는 일부러라도 한 번씩은 거치게 하는 편이다. 재발명하면서 기반 시스템의 구조에 대해서 알아갈 수 있다는 것이 이유다.] 하는 식의 과제들이 많으므로 바닥부터 훑어가며 견문을 넓히는 데 좋다. 실제로 가장 기저에 놓인 OS API[* 유닉스의 [[POSIX]] API, 윈도우의 [[Windows API]] 등]는 오늘날 플랫폼을 불문하고 거의 다 C언어로 되어 있고, 그 외에도 대부분의 인프라가 되는 소프트웨어는 C언어로 만들어진 후 타 언어로의 바인딩을 제공하는 식이다. 로우 레벨부터 단계를 높여가며 관찰을 해보면, 머신 코드는 머신에 따라 달라지고, 어셈블리어도 Intel/AT&T 등 문법에 따라 몇 가지 버전이 존재하지만, 그 위쪽에서 결국 C언어로 대통합이 이루어진다. 그리고, C언어 위쪽으로 가면 다시 C++/Java/C#/Objective-C/Python 등으로 다양하게 갈라진다. 즉, 두 개의 원뿔을 꼭짓점끼리 붙여 놓은 형태이며, 저 꼭짓점 부분에 C언어가 존재하는 형태이니, 이것만으로도 C언어의 중요성은 충분히 알 수 있다. 그래서 이런 견문은 실제로 나중에 더 이상 C언어를 쓰지 않고 타 고급 언어로 넘어가더라도 유용한 경우가 많다. (실제로, 많은 수의 언어가 C언어와의 FFI를 제공한다.) 즉 결론만 말하자면 C언어를 배우면 활용도가 매우 높다는 말. C언어만 알아도 같은 절차지향 프로그래밍 언어뿐만 아닌, 객체지향 프로그래밍 언어도 어느정도 이해할 수 있다. 물론 이해했다는건 단편적이고 객체지향에 대해 공부는 조금 더 해야하긴한다. 하드웨어나 컴퓨터 아키텍처를 배우게 된다면, C언어의 특징은 오히려 장점이 된다. Java나 Python 같은 언어들은 일반적인 상황에서 생산성을 높이기는 좋지만 특정한 상황에서 속도를 높이기는 어렵다. 일반적인 개발을 하려면 많은 상황을 처리할 수 있도록 강력하고 복잡하게 만들어야 하기 때문이다. 따라서 고성능이 필요한 특정 목적이 필요할 경우 언어에서 쌓은 추상화의 장벽을 뚫고 저수준(low level) 개념을 이용할 필요가 있는데, 이에 관한 개념을 제대로 이해하려면 처음부터 OS와 기계 제어를 위해 태어난 C언어를 사용하는 것이 가장 효과적이다. 다시 말해, C언어를 공부한다는 말은 곧 하드웨어를 공부한다는 말과 같다고 할 수 있다. === 단점 === '''성능'''이라는 대명제에 충실해서 작게는 변수 초기화, 배열 범위 점검, 널 포인터 문제에서부터 크게는 [[쓰레기 수집]](Garbage Collection; GC), 예외 처리 같은 것까지 조금이라도 하드웨어에 오버 헤드가 걸릴 것 같은 기능은 다 무시하기 때문에 주니어 프로그래머에게는 어렵다. 프로그래머가 메모리 관리까지 전부 신경써야 하는 것이다. 현재 쓰이는 고수준 개념들 자체는 의외로 오래된 경우가 많다. 예를 들어서 [[쓰레기 수집]]은 1959년에 최초로 구상됐고, 타입 에러를 컴파일 타임에 모두 잡아낼 수 있는 Hindley-Milner 타입 인터페이스가 1970년대 후반에 나와서 [[Haskell]] 등지에서 쓰이고 있다. [[클로저]] 개념도 1960년대~70년대에 나왔다. 시간상으로는 지원한다 해도 이상하지 않다. 그럼에도 이런 기능을 C89/C90가 지원하지 않았던 이유는, 당시 언어에 고수준 개념을 구현하기에는 하드웨어의 성능이 절대적으로 떨어졌다는 점이다. C언어가 컴파일러를 거쳐 기계어 파일이 나오면 그걸 다시 사람이 직접 최적화를 해줘야 했다. 당시 컴파일러의 [[프로그램 최적화]] 성능이 떨어졌던 이유도 있겠지만, 당시 하드웨어는 초고도로 최적화를 하지 않으면 만족할 만한 속도가 나오지 않았다. 그래서 그 당시에는 프로그래머라면 저런 부분은 알아서 관리해가며 쓰는 것이 '''기본'''이었다. 어셈블리어보다 이식성이 좋다고는 하지만, 하드웨어마다 달라지는 부분들을 언어 내에서 컨트롤해서 일관성을 유지하는 것이 아니라, 성능을 위해서 전혀 후처리를 하지 않고 그대로 프로그램에 반영해버리므로 사실 C언어의 이석성도 미신이라는 사람들이 많다. 그대로 때려박는 특성상 컴퓨터 아키텍처가 다르면 똑같게 동작할 리 없다는 것이 이유다. 그나마, C99에서는 컴퓨터 성능이 좀 올라간 것을 반영해서 여러가지 엣지 케이스에 대해 어느 정도 통일성을 만들려고 한 노력이 엿보이긴 한다. 다음은 C언어 사용 시에 어려움을 느끼기 쉬운 부분들이다. * 느슨한 타입 검사: 특히 포인터와 관련하여 문제가 생기기 쉽다. * 범위를 벗어난 배열 접근: 배열에 접근할 때, 인덱스가 배열 범위를 벗어나도 이를 체크하지 않는다. 이를 이용한 flexible array member와 같은 기능도 존재한다.[* 원래는 zero-sized array라는 일종의 테크닉이었는데, C99에서 정식으로 편입됐다.] 문제는 이것이 [[버퍼 오버플로]] 취약점이라는 심각한 보안 버그로 이어질 수 있다는 것이다. 물론 프로그래머가 꼼꼼히 체크하면 되긴 하는데 사람이 실수를 하지 않을 수는 없기 때문에...[* 버퍼 오버플로 취약점을 이용하면 배열 경계를 넘겨서 그 위에 선언한 변수들을 하나하나 덮어쓰기가 되고, 최종적으로 리턴 주소(함수의 실행을 끝낸 후 다시 함수를 호출한 곳으로 돌아가는 주소)까지 덮어쓰는 게 가능해진다. 이를 응용하여 기존 스택 프레임에 바이트를 조작하여 실행 가능한 기계어 코드를 주입하고, 반환 주소에 주입한 코드의 처음 주소를 가리키게 하여 공격자가 인위적으로 만들어낸 코드를 실행시키는 공격 기법을 코드 인젝션(Code Injection)이라 한다. 기본적으로 이 취약점을 가진 프로그램을 네트워크에 물리면 원하는 동작을 원격에서 실행할 수 있게 되며, 최악의 경우는 [[루트]] 권한으로 실행되는 프로그램에서 리턴 어드레스를 셸을 실행하는 코드가 있는 곳으로 덮어쓰면 루트 계정을 원격으로 탈취당할 수도 있다. 이를 버퍼 오버플로 취약점이라고 한다. 1998년 전 세계 서버를 감염시킨 모리스 웜도, finger라는 유닉스 유틸리티의 버퍼 오버플로 취약점을 이용했다. 이 웜은 쉽게 들통나지 않도록 여러가지 [[카무 플라주(위장)|위장]] 전략이 많이 포함되어 있었고, 코넬 대학은 결국 서버를 다운시키는 등의 조치를 취했지만 전 세계로 퍼져나갔다. 당시 이 웜을 만든 23세의 모리스는 벨 연구소에서 유닉스의 로그인 암호화를 담당했던 사람의 아들이었고, 현재 MIT 대학의 교수다. 2001년 한국에도 사이버 대란을 일으킨 코드 레드 [[웜]]의 경우 전세계의 서버 몇 십만 개를 감염시킨 사례가 있다. 이 취약점 때문에 경계 체크를 안 하는 gets 같은 표준 함수 여러 개를 deprecated(사용 자제) 처리해야 했고, printf의 포맷 문자(\\n) 하나가 날아갔다. 심지어 운영체제 자체에서 버퍼 오버플로 방지 메커니즘을 제공하기까지 하는데도 간간히 뚫리는 게 이 취약점이다. 물론 공돌이들이 손 놓고 있는 게 아니니 방지책도 많이 마련되어 있긴 하지만 어쨌든 [[내려갈 팀은 내려간다|뚫릴 취약점은 뚫린다]]. 2014년 [[OpenSSL]]에 생긴 재앙적인 버그인 [[하트블리드 사태|하트블리드]]도 근본적으로는 C언어가 배열의 경계를 체크하지 않는다는 점에서 생겼다.][* visual studio 2012 버전부터 함수에 _s 가 붙은 (printf_s, scanf_s 등) 보안을 위한 함수가 추가됐다. 기존의 printf 같은 함수는 그냥 쓸 수 있지만 scanf와 같은 함수를 쓰려고 하면 보안에 따른 에러 메시지가 뜬다. Visual Studio에서는 {{{_CRT_SECURE_NO_WARNINGS}}}를 전처리기에 선언하라고 안내한다. 그리고 이 안전 함수들은 C11에도 추가됐다.] * 문자와 문자열에 대한 추상화 부재: C에서는 문자에 대해 적절한 추상화를 제공하지 않고 날 것의 숫자 코드 그대로 처리하며, 문자열에 대해서도 string과 같은 타입이 따로 없고 그 대신에 char형 배열을 그대로 사용한다. 언어 자체적으로 이를 간편하게 다루는 기능이 없기 때문에 표준 문자열 함수에 의존해서 처리해야 하며, 초보자들이 잘못 이해하거나 혼란을 느끼기도 쉽고 실수를 하거나 버그를 만들기도 쉽다.[* 예를 들어 대문자 판별을 위해 c >= 'A' && c <= 'Z' 와 같이 쓰는 경우가 많은데, 이는 EBCDIC 코드와 같이 A부터 Z까지 연속이 아닌 문자셋에서 문제가 발생한다. 따라서 isupper()와 같은 함수로 판별하는 것이 바람직하다.][* 특히 주로 문자열 상수(String literal. {{{ "str" }}} 같은 따옴표로 둘러싸인 부분을 뜻함.)에 대해 잘못 이해하는 경우가 많은데, 문자열 상수 자체는 '문자열'이나 '값'이 아닌 '배열'이며, 결과적으로는 해당 배열의 첫 번째 글자가 저장된 위치를 가리키는 '주소 값'이 된다. 이걸 제대로 다루기 위해서는 악명높은 포인터까지 완전히 배워야 하기 때문에, 언어 난이도가 급상승한다.] * 문자열 처리 방식상의 취약점: C언어에서는 모든 비트가 0인 널(null, \\0) 문자를 써서 문자열의 마지막을 표현하는데, 실수로 널 문자열을 덮어쓸 경우 경계를 침범하기도 쉽고, 문자열의 길이를 구하려면 매번 길이를 세어 보아야 한다는 문제가 있다.[* 비교삼아 다른 언어의 문자열 처리 방식을 살펴보자면, 파스칼과 같은 언어는 문자열의 길이를 맨 앞에 따로 저장하여 처리한다.[[https://wiki.freepascal.org/Character_and_string_types#String|#]]] * 배열과 포인터의 혼동: C언어의 배열은 문맥 상황에 따라 포인터로 바뀌는 경우가 많고, 따라서 초보자가 느끼기에 무척 혼란스럽고 구분이 어렵다. 심지어 익숙해진 다음에도 버그를 만들기가 쉽다.[* 덕분에 교재마다 접근 방법이 달라지는데, 어떤 교재에서는 '비슷하다'고 전제한 뒤 차이점을 설명하는 식이고, 어떤 교재에서는 '다르다'고 전제한 뒤 공통점을 설명하는 식이다. 어느 쪽으로 접근하더라도 함정과 예외가 상당히 많아지기 때문에, 둘의 차이를 충분히 구분할 만한 상황적 경험이 적을 수밖에 없는 초심자들에게 결국은 이해보다 암기로 흘러가고, 어렵게 느끼는 경우가 많다.] * 네임 스페이스 미지원: C언어는 C++과 달리 네임 스페이스를 여러 단계로 구분하지 않기 때문에, 함수 이름과 전역변수끼리 서로 충돌이 날 가능성이 높아진다. C언어에서 서로 이름이 충돌하지 않게 하는 유일한 방법은 충분히 길게 이름을 짓고 다른 라이브러리와 겹치지 않게 기도하는 것 뿐이다.[* 소스 수준에서 play_sound라는 함수를 어디엔가 정의를 해 놓고 다른 소스 파일에서는 play_sound라는 이름만 같은 다른 함수를 만들고 같이 컴파일하면 에러가 난다. 더욱 골때리는 건, 컴파일 단계는 무사히 진행되는데 링커 수준에서 에러가 난다는 것. 따라서, 외부 소스 파일로 노출시키고 싶지 않은 내부 함수들은 static 지시자를 앞에 붙여줘서 이름 유출을 방지하고 다른 소스에서 쓸만한 함수는 <모듈 이름>_함수 이름(e.g. NamuWiki_add_document)을 사용하여 이름 충돌을 최소화 하는 게 일반적이다. 이는 사실 장점이자 단점인데, C++에서는 컴파일된 심볼명에 개별 지시자를 넣어 다른 네임 스페이스나 클래스의 함수 등이 충돌이 일어나지 않으나, 문제는 [[C++]] 표준에는 이 Naming Mangling에 대한 표준이 정의되어 있지가 않아 컴파일러마다 호환이 되지 않는다는 점이다. 그러나 C언어는 이러한 네이밍을 하지 않기 때문에 컴파일러 호환성 유지가 가능한 한 가지 방법이며, 이 경우 [[C++]]로 구현되어 있으나 외부 API를 제공하는 경우 C언어형 네이밍 스킴을 사용한다.] * 각종 형변환 규칙: 정수 승격, 일반 산술 변환, 기본 인자 진급 등 암묵적으로 수행되는 생소한 형변환 규칙들이 학습을 어렵게 만들고 학습 이후에도 프로그래머의 실수를 유도한다.[* 특히 정수형 계산 관련하여 골치 아픈 사례들이 많은데, 대표적으로는 부호형(signed)과 무부호형(unsigned)이 만나 음수가 양수로 변하는 마술이 있다.] * 예상하기 어려운 최적화, 부수 효과(side effect): C언어는 불필요하다고 판단되는 수식을 평가하지 않을 수 있다. 즉, 극단적으로 코드를 변형하거나 제거하여 최적화를 수행할 수 있다. 만약 프로그래머가 코드를 올바르게 작성하지 않는다면 컴파일러는 이를 잘못 판단하여 최적화 과정에서 예상하기 어려운 오동작을 만들어낼 수 있다. * bool 타입의 부재: C에서는 정수형이 bool 타입을 대신한다. 0은 false이고, 나머지 다른 것들은 전부 true로 처리한다.[* 음수도 true로 처리된단 뜻이다. 없으면 define 문으로 선언해서 쓰면 된다.] 때문에 임의의 char 값이 숫자인지 알아보는 isdigit 함수는 숫자가 아니면 0을 리턴하고 숫자일 경우 보통 1을 리턴하긴 하지만, 0이 아닌 그냥 어떤 수를 리턴하는 컴파일러도 있다. 매뉴얼 페이지에는 보통 non-zero라고 되어 있다. 비슷하게 논리적 부정 연산을 의미하는 !의 경우는 0일 경우 1로, 0이 아닌 다른 모든 값은 0으로 바꾼다.[* 다만, C99에서 _Bool 타입이 생기긴 했다. stdbool.h를 포함할 경우, 그냥 bool로 사용도 가능하긴 하다. 왜 그냥 bool로 안 넣었냐면, 기존 프로그램 중에 bool 이름을 사용한 코드가 있을 가능성이 있기 때문. 반면, 언더 스코어(_) 뒤에 대문자가 오는 이름은 C언어 표준에서 사용하지 말라고 먼저 명시해놨기 때문에 이것을 사용한 _Bool이 됐다.] C언어에는 저런 함정들이 매우 많이 도사리고 있으며, 이러한 것들이 가장 기초적인 단계에서부터 서로 얽혀 등장한다. C언어를 배운다는 것은 사실 '어떻게 프로그램을 만들 것인가'를 배우는 게 아니라, '어떻게 저런 함정을 피해갈 것인가'를 배우는 거라는 사람도 있다. C언어는 타 언어에 비해 기계에 좀 더 가까운 얇은 추상화를 제공하기 때문에, 사용자가 기계에 대해 더 잘 알고 있어야 하고 예외인 경우도 많으며 그에 비해 안전장치는 굉장히 빈약하다. 따라서 위와 같은 여러 어려운 부분들이 생기기 쉽다. 하지만 반대로 저레벨 제어를 할 때는 변수 타입이나 참조 등에 제약이 적어 다른 언어보다 편하고 효율적인 점도 있다. 예를 들어서 블록 암호화 같이 비트/바이트 단위로 바이너리를 자유자재로 조작해야 하는 코드는 고수준 언어로 짜기 불편하다. 익숙해지면 구조체 같은 사용자 정의 데이터 타입을 이리저리 캐스팅해서 포인터 연산을 활용해 전혀 엉뚱한 데이터로 변환해서 쓰는 것도 가능하다.[* 소켓 프로그래밍이 보통 이렇다. 그리고 사실 구조체, 배열, 공용체는 다른 타입과의 포함 관계라서 문법적으로 같은 주소/다른 타입이 가능한 경우이기도 하다.] 사실, 초창기 C언어는 비교적 사용하기 편리한 고수준 언어로 분류됐고 그렇기 때문에 큰 인기를 끌었지만, 오늘날 C언어는 오히려 불편한 언어에 속한다. 그럼에도 불구하고 많이 사용되는 이유 중 하나는 투명성이다. 고수준 언어들의 경우, 하드웨어로부터 거의 완전히 추상화를 시킨 경우가 많기 때문에 프로그램 로직에만 신경 쓰면 된다는 장점이 있지만, 그게 정확히 컴퓨터에서 어떤 식으로 돌아가는지를 예측하기는 그 추상화 수준만큼 힘들어지게 된다. 반면, C언어는 기능 자체가 적고 하드웨어에 맞춤 형태로 최소 한도의 추상화만 시킨 수준이기 때문에, 어셈블리어와의 호환성도 좋고 코딩과 동시에 실제 어떤 식으로 하드웨어가 움직일지 예상이 비교적 쉽다. 그렇기 때문에 C언어로 코딩을 한다는 것은 곧 저런 장점을 살리고 싶다는 것이고, 그러려면 결국 컴퓨터 아키텍처에 대한 지식도 필요하며, C언어 자체에 대해서도 아주 디테일한 수준까지 알고 있어야 한다. 이런 측면 때문에 언어 자체가 간결하다고 하여 복잡한 기능들을 많이 제공하는 고수준 언어들에 비해 쉽다고 보긴 힘들다. 이것은 별개의 이야기이며, 어느 정도 사람마다 의견이 갈리기는 하나, 포인터에 대한 이해가 빠르다면 오히려 JAVA같은 객체지향 언어보다 C언어가 편하다는 사람들이 많다. 이는 객체지향의 주 포인트인 '''추상화, 캡슐화, 상속, 다형성'''이 C에서 없거나 다른 방식으로 구현되기 때문인데, 아무래도 처음 JAVA 등을 접하는 사람은 그냥 위에서부터 아래로 책 읽듯이 읽으면 되는 프로시저 언어에 비해 이리갔다, 저기갔다, 오버라이딩도 하고, 추상화 메서드도 있고, 인터페이스도 있어서 혼란스러운 JAVA 같은 것보다는 훨씬 보기 수월하기 때문. 물론 처음에 이런 불편함을 느꼈던 초보자들이나 프로시저 언어에 매우 익숙했던 사람들도 점차 적응이 되다보면 C가 생각보다 불편한 언어였다는 것을 알고 메롱메롱 하기도 한다. === 저수준 언어로서의 C === C언어는 저수준 언어와 고수준 언어의 특성을 둘 다 가진다. 그 중에서 특히 주목받는 것은 저수준 언어로서의 강력함이다. 비록 이식성을 추구하기 위해 어느정도 추상화를 거치긴 했으나, C언어는 정수형 모델, 비트 연산, 공용체, 포인터, 형변환 규칙 등 다양한 부분들에서 기계에 대한 직접적인 접근을 의도하고 있다. C언어는 처음부터 어셈블리어와 비교할만한 효율을 가지게 저수준으로 설계됐다. K&R의 "C programing language" 책의 초판 서문에서도 C언어를 어셈블리어를 대체하는 이식성 있는 어셈블리어(portable assembler)로 만드는 것을 목표로 설계됐음을 밝히고 있다.[* 서문 내용: C is a relatively "low level" language. This characterization is not pejorative; it simply means that C deals with the same sort of objects that most computers do, namely characters, numbers, and addresses. ......... Again, because the language reflects the capabilities of current computers, C programs tend to be efficient enough that there is no compulsion to write assembly language instead. ......... Although C matches the capabilities of many computers, it is independent of any particular machine architecture, and so with a little care it is easy to write "portable" programs...] C언어가 주로 쓰이는 곳이 저수준 제어가 필요한 분야이다 보니, 많은 C언어 구현체들이 인라인 어셈블러를 통해 [[어셈블리어|어셈블리 코드]]를 코드 안에 직접 집어넣을 수 있는 확장 기능을 적극적으로 지원한다. 이런 경우 호환성을 희생하고 속도를 얻을 수 있다. === 고수준 언어로서의 C === C언어가 저수준에서 가지는 강력함에도 불구하고, C언어는 분명히 고수준 언어이며, 추상성에 대해 아래에서 설명할 매우 강력한 규칙을 가지고 있다. 다만 C언어가 가정하는 추상 기계가 실제 CPU 및 기계와 상당히 가깝게, 기계어로 번역하기가 편하게, 다양한 하드웨어에서 효율적으로 돌아갈 수 있도록 잘 만들어져 있을 뿐이다. 추상층이 얇을 뿐이지 그 얇은 추상층은 소스 코드와 그것이 번역된 실행 파일을 엄격하게 분리한다. C언어는 소스 코드를 번역할 때, 어떤 추상 기계를 가정하여 그 기계가 의미론적으로 동작하는 원리에 따라 프로그램을 번역하고 생성한다. 의미론적이라는 얘기는 실제 과정이나 동작에 상관 없이 결과만 같으면 된다는 뜻이다.[* 예를 들어 1부터 100까지 루프를 통해 합을 구할 때, 그냥 5050을 대입해도 상관없다.] 또한 의미있는 결과나 부작용을 가지지 않는다고 판단하는 부분에 대해서는 그냥 평가하지 않아도(없애버려도) 무방하다.[* 예를 들어 시간 지연을 위해 집어넣은 루프를 없애 효과가 없는 경우가 발생한다.][* 또 다른 예로는, if (signed_i+1 [[파일:이것이C언어다.jpg|width=200]] || || 저자 || 서현우 || || 출판 || 한빛미디어 || 뇌를 자극하는 C 프로그래밍의 저자가 집필한 C언어 입문서. 보다시피 표지에 건담 프라모델이 있는 것이 특징.[* 한빛미디어의 "이것이 ~다" 시리즈에는 앞표지에 모두 건담 프라모델이 들어가 있다. 다만 책별로 모델은 다르다.] --건담...?-- 입문서이기 때문에 열혈 C 프로그래밍과 비슷한 한계를 지니고 있지만 C언어 첫 번째 교재로서 많이 추천받는 교재로 평가받고 있다.[* 대학에서 프로그래밍 입문 교재로 쓰는 경우도 있다.] 또한, 2019년부터 책의 내용은 거의 그대로 유지한 채 개정 연도인 2019년에 맞춰 컴파일러를 [[Visual Studio]] 2013에서 2019로 바꾸고, 가독성과 가시성을 높인 개정판 '혼자 공부하는 C언어'가 출판되고 있다. === 터보 C 정복 === * 저자: 임인건 * 출판: 가남사(1999) PC통신 시절 국내 한정으로 C언어 레퍼런스 중 하나만 꼽으라고 하면 열의 다섯은 주저 없이 이 책을 꼽았던 명저로, 특히 배열과 포인터에 관한 설명은 당시 국내 도서 중에서는 비교 대상이 없다는 평가를 받았던 책이다. 1299페이지라는 압도적인 두께가 흠이긴 하지만, 그만큼 물샐 틈 없이 설명을 해주고 있다. 다만, 지금 시점에서 읽겠다면 시대적인 한계와 Turbo-C를 기준으로 쓰여진 책이라는 점은 고려를 해야 할 것이다. 1991년에 벌써 5판이 발매된 너무 오래된 책이기도 하거니와, 요새처럼 C언어 표준 드래프트 문서를 곧바로 받아볼 수 있는 시대에는 그 자세한 설명도 의미가 퇴색될 수밖에 없다. 저자인 임인건씨는 도스 시절 한라프로라는 인기 한글 라이브러리를 만들었던 사람으로, 그의 PC통신 아이디인 터보이빨(turbo28)과 프로그래머 십계명으로도 유명하다. === 기타 관련 자료 소개 === * C언어 표준문서 최종 초안들: C언어 표준 문서는 [[https://www.iso.org/standard/74528.html|ISO로부터 198스위스프랑(20~30만원 정도)에 구입]]하거나 혹은 그 외의 [[https://codeday.me/ko/qa/20190304/409.html|다양한 경로로]] 구할 수 있다. 하지만 학생 수준에서는 적지 않게 부담이 되기 때문에 이용할 수 있는 것들이 바로 인터넷상에 공개된 최종 초안(Final draft)들이다. 최종 초안들이니만큼 완전히 같지는 않겠지만, 공부 또는 기본적인 사항들에 대해 참고하기 위해서라면 충분한 수준이다. * [[https://web.archive.org/web/20181230041359/http://www.open-std.org/jtc1/sc22/wg14/www/abq/c17_updated_proposed_fdis.pdf|C18(N2176)]] * [[http://www.open-std.org/JTC1/SC22/WG14/www/docs/n1570.pdf|C11(N1570)]] * [[http://www.open-std.org/JTC1/SC22/WG14/www/docs/n1256.pdf|C99 + TC1 + TC2 + TC3(N1256)]] * [[http://www.open-std.org/JTC1/SC22/WG14/www/docs/C99RationaleV5.10.pdf|rationale for the C99 standard]] * [[http://c-faq.com/|C FAQ]]: comp.lang.c 뉴스그룹의 주요 질문과 답변을 Steve Summit가 정리한 문서. 입문서의 범위를 완전히 공부한 이후 중급자로 가는 다리 역할을 해 줄 수 있는 문서이다. 신성국씨가 정식으로 허가를 받고 번역한 문서가 있다. [[http://cinsk.github.io//cfaqs/index.html|C FAQS 한국어 번역판]] * [[http://david.tribble.com/text/cdiffs.htm|Incompatibilities Between ISO C and ISO C++]]: C99와 C++98과의 차이점을 David R. Tribble가 정리한 문서. 이 또한 신성국씨의 번역본이 있다. [[http://cinsk.github.io//iso-c-diff-iso-c++/index.html|ISO C와 ISO C++의 차이]] * [[https://dojang.io/course/view.php?id=2|C언어 코딩 도장]][* 책을 구매하지 않으면 심사 문제만 접근할 수 있도록 사실상 유료화 됐다.] * [[http://www.joinc.co.kr/modules/moniwiki/wiki.php/Site/Beginner/StudyHowTo|JoinC]] * [[http://www.c-jump.com/pagerules02.html|C언어 보드게임]][[http://www.c-jump.com/pagedownload07.html|다운로드 링크]] * [[http://coffeenix.net/doc/develop/knr2rfm.pdf|C 레퍼런스 매뉴얼 번역본]]: 전웅씨가 K&R 2판 부록의 레퍼런스 매뉴얼(ANSI C또는 C89의 요약본)을 번역하고 해설을 첨가한 번역본. C89를 기반으로 하고 있기에 다소 오래된 내용이지만, 분량이 72쪽으로 적은 편이라 표준문서가 어떤 형식으로 되어있는지 익히는데 큰 도움이 된다. * 씹어먹는 C언어: [[https://github.com/kev0960/ModooCode/raw/master/book/c/main.pdf|PDF(링크 클릭시 바로 다운로드되니 주의)]]와 [[https://modoocode.com/231|웹 버전]]이 있다. == C언어용 개발 도구들 == * [[Visual Studio]] [[http://www.visualstudio.com/ko/|한국어 공식 사이트]] [[마이크로소프트]]에서 만든 [[통합 개발 환경|IDE]]. Visual Studio 2019 16.8이후 부터 C언어 표준과 C++언어 표준을 각각 지원한다. [[https://docs.microsoft.com/ko-kr/cpp/overview/install-c17-support?view=msvc-170|출처]][* 여기서 ISO C17(2018)은 C18이다.] * [[CLion]] [[https://www.jetbrains.com/clion/|공식 사이트]] [[IntelliJ IDEA]]로 유명세를 날리고 있는 [[JetBrains]]에서 개발한 C/C++ IDE이다. 인터페이스가 직관적이고 다양한 종류의 컴파일러로 크로스플랫폼 개발이 가능하다는 장점이 있다. [[Make|CMake]] 기반으로 프로젝트를 생성하며, 유료 구독권 형식으로 판매되고 있기 때문에 월/년마다 정기 구매해야 한다. 윈도우 환경에서 [[유닉스/MS 윈도우|WSL]]에 접속하여 리눅스 기반 컴파일을 할 때 가장 편리한 툴이기도 하다. 또한 유일하게 제대로 된 윈도우 환경에서의 C언어 IDE이기도 하다. * [[Xcode]] [[https://developer.apple.com/xcode/|공식 사이트]] [[Apple|애플]]에서 직접 제작한 IDE. 예전에는 [[GCC]]를 그대로 가져다[* 사실은 애플이 GCC를 가져다가 사용하는 대신, 자체적으로 GCC에 추가한 기능 일부를 다시 GCC 측에 돌려주기로 약속했었다.] 썼지만, 요즘은 [[LLVM]]이라는 새 컴파일러 셋으로 이주했다.[* 게다가 LLVM은 이것을 처음으로 고안한 사람을 애플이 스카우트하면서 거의 애플 소유의 프로젝트가 됐다. 하지만 [[스티브 잡스]]의 애플 복귀 이후 애플이 진행하는 대부분의 소프트웨어 프로젝트가 오픈 소스인지라 이것도 역시 오픈 소스로 계속 진행중. ~~ [[오라클(기업)|오라클]] 보고 있나? ~~] C언어, C++, Objective-C, Swift 등의 언어를 컴파일할 수 있다. macOS용 애플리케이션이나 iOS용 앱을 제작하는 데는 필수이다. * [[Visual Studio Code]] [[https://code.visualstudio.com/|공식 사이트]] [[마이크로소프트]]의 [[문서 편집기|텍스트 에디터]]로, [[https://marketplace.visualstudio.com/items?itemName=ms-vscode.cpptools|C/C++ 플러그인]]을 설치하면 VS와 동일한 인텔리센스가 제공된다. IDE가 아니므로 컴파일러와 디버거, 빌드 툴 등을 직접 세팅해야 하지만, 그만큼 VS에 비해 가벼우므로 환경 구성법만 안다면 단순 코드 작성에는 이쪽이 나을 수 있다. * [[넷빈즈]] [[https://netbeans.apache.org/|공식 사이트]] 오픈 소스 IDE 중 하나로, 원래 [[오라클(기업)|오라클]]에서 배포했으나 2016년에 [[아파치 소프트웨어 재단]]으로 소유권이 이전됐다. * [[이클립스(통합 개발 환경)|이클립스]] CDT [[https://eclipse.org/cdt/|공식 사이트]] 오픈 소스 IDE인 [[이클립스(통합 개발 환경)|이클립스]]의 C언어/C++ 개발용 플러그인이다. * [[Code::Blocks]] [[http://www.codeblocks.org/|공식 사이트]] C/C++/Fortran용 오픈 소스 [[통합 개발 환경]]이며 라이선스는 [[GPL]] 3.0 버전을 따르고 있다. * Bloodshed Dev-C++ [[http://www.bloodshed.net/devcpp.html|공식 사이트]] [[GPL]] 라이선스를 따르는 오픈 소스 IDE. 2006년 이후로는 소식이 없다. 설치 속도가 빠르고 편리하지만 리소스 에디터가 없다. 설치할 때 기본적으로 같이 깔리는 [[컴파일러]]는 MinGW+GCC. * Orwell Dev-C++ [[http://orwelldevcpp.blogspot.kr/|공식 사이트]] 오웰(Orwell)이 Bloodshed Dev-C++ 4.9.9.2 소스로 개발하고 있는 IDE이다. 2015년 이후로는 무소식. * Borland C [[http://edn.embarcadero.com/article/20633|지원 페이지]] [[볼랜드(기업)|볼랜드]]에서 개발한 유료 IDE. MS-DOS 시절에는 터보 파스칼과 함께 빠른 컴파일 속도로 인기가 많았으나, [[Microsoft Windows|윈도우]]의 시대가 오면서 점차 Visual Studio에 밀리게 됐다. 단순 컴파일러는 현재 무료로 다운로드 가능하다. 볼랜드가 개발 언어 쪽만 전담하는 코드기어라는 자회사를 설립하면서 모든 권한을 넘겼는데, 코드기어가 엠바카데로와 합병되면 홈페이지가 여러 차례 이동됐다. 참고로 델파이의 개발도 볼랜드 → 코드기어 → 엠바카데로의 순서로 넘어갔다. * Turbo C++ [[https://www.developerinsider.in/download-turbo-c-for-windows-7-8-8-1-and-windows-10-32-64-bit-full-screen/|다운로드 페이지]] 볼랜드 Turbo C++를 Windows 7, 8, 10을 위해 확장한 버전. 그 외에는 소식이 없다. * Watcom C [[http://www.openwatcom.org/index.php/Main_Page|공식 사이트]] 도스 시절 끝무렵에 DOS/4GW라는 메모리 확장 프로그램과 함께 잠깐 동안 쓰였다(8.5 버전부터 포함됐다). MS-DOS의 640KB 메모리 한계를 넘어 64MB까지의 메모리를 손쉽게 사용할 수 있게 해 주었기 때문이다. 그 당시의 게이머들이라면 실행 초기에 DOS/4GW라고 뜨던 안내문을 기억할 것이다. 공식 사이트가 [[위키]] 형식으로 되어 있다. Open Watcom Public License라는 라이선스를 따른다. * LCC [[https://en.wikipedia.org/wiki/LCC_%28compiler%29|위키백과 영문]] A Retargetable C Compiler: Design and Implementation라는 책에 소스 코드가 실려있는 C언어 컴파일러. 데이브 핸슨(Dave Hanson)과 크리스 프레이저(Chris Fraser)가 만들었다. 아래에 설명하겠지만 이를 기반으로 하는 컴파일러가 몇몇 존재한다. * lcc-win [[https://lcc-win32.services.net/|lcc-win]] 위의 LCC를 바탕으로 한 윈도우용 C언어 컴파일러. 제이컵 나비아(Jacob Navia)가 만들었다. 월간 마이크로소프트웨어를 통해 국내에 소개된 적이 있다. * Pelles C [[http://www.smorgasbordet.com/pellesc/|공식 사이트]] 위의 LCC를 기반으로 스웨덴의 펠레 오리니우스(Pelle Orinius)가 개발한 컴파일러. 윈도우 전용의 프리웨어 통합 개발 환경이다. MS와는 다르게 C99는 물론이고, C11도 완벽 지원하는 컴파일러를 제공한다. 게다가 툴이 가볍고 무료다. * ICC (Intel C++ Compiler) [[https://en.wikipedia.org/wiki/Intel_C%2B%2B_Compiler|위키백과 영문]] [[https://software.intel.com/en-us/c-compilers|공식 사이트]] [[인텔]]에서 자기들이 만든 CPU에 최적화된 코드를 만들어 낼 수 있도록 직접 제작한 컴파일러 스위트. 사용 설명서 시작 부분에 '인텔에서 제작하지 않은 CPU에서 구동 시 최적화된 성능을 보장할 수 없습니다.'라고 적혀 있다.[[https://software.intel.com/en-us/articles/optimization-notice#opt-en|#]] C언어/C++ 및 [[포트란|Fortran]] 컴파일러를 제공한다. 윈도우에서 설치 시, Visual Studio에 애드온 형태로 설치가 돼서 Visual Studio 내에서 기존 컴파일러 대신에 사용할 수 있다. 컴파일러 이외에도 [[어셈블리어]] 단위로 한땀한땀 손으로 최적화한 수치해석 라이브러리[[https://en.wikipedia.org/wiki/Math_Kernel_Library|#]]와 다수의 컴퓨터가 동시에 컴퓨팅을 할 때 사용되는 MPI 라이브러리, 코드의 성능을 분석해주는 도구[[https://en.wikipedia.org/wiki/VTune|#]], 코드 최적화를 도와주는 도구[[https://en.wikipedia.org/wiki/Intel_Advisor|#]], 성능에 악영향을 주는 에러를 찾아주는 도구[[https://en.wikipedia.org/wiki/Intel_Inspector|#]], 등을 하나로 묶어서 [[https://software.intel.com/parallel-studio-xe|Intel Parallel Studio]]라는 이름으로 판매한다. 인텔 CPU와 인텔 가속기를 수만 개씩 사용하는 슈퍼컴퓨터 등에서는 매우 자주 쓰이는 유용한 도구. Intel Parallel Studio는 학생 대상으로 무료로 사용 가능(윈도우용은 Visual Studio 통합 포함)하고, 수치 해석 라이브러리는 일반인 대상으로 무료 사용 가능하다. === 관련 문서 === * [[WIPI]] == 여담 == C언어의 [[추종자]]들은 다음과 같은 소리를 한다. >전산과 신입생은 CPU부터 시작해서 C언어를 활용하는 데까지 차곡차곡 기초를 닦아야 합니다. 저는 솔직히 너무나도 많은 컴퓨터 관련 교육 과정들이 자바가 가장 좋은 초보자용 언어라고 선전하는 현실에 질려 버렸습니다. 흔히 자바는 쉽고, 따분한 문자열이나 malloc과 같은 골칫덩어리를 다루는 과정에서 혼란을 겪지 않으며, 아주 큰 프로그램을 모듈로 나눠서 만들 수 있는 근사한 객체 지향 프로그래밍 기법을 배울 수 있다는 화려한 이유들이 따라 나옵니다. 하지만 여기에는 교육적인 재앙이 있습니다. 졸업생들은 하향 평준화돼 러시아 페인트공 알고리즘[* 처리할 데이터의 양이 커지면 처리 시간이 지나치게 증가하는 알고리즘.]을 여기저기에 만들어내며, 심지어 자신의 잘못을 인식조차 못할 겁니다.[* 이는 [[알고리즘]]의 문제이지 C언어를 모름으로써 발생하는 문제가 아니다.] 펄 스크립트에서 이런 사실을 결코 볼 수 없을지라도, (물론 어렵지만) 기본적으로 문자열이 무엇인지 아주 깊은 단계에서 이해하지 못하기 때문입니다. 다른 이들이 뭔가를 잘하도록 가르치길 원한다면, 기초부터 시작해야 합니다. 이는 마치 [[베스트 키드]]와 비슷합니다. 마루바닥을 쓸고 닦고 쓸고 닦고, 이렇게 3주만 하면, 자연스럽게 목표물을 향해 발이 쭉쭉 뻗어나갑니다. > >-- 조엘 온 소프트웨어 (조엘 스폴스키) C언어를 깊게 공부하면 시스템의 저수준에 대해서 이해하는데 많은 도움이 되지만, 그렇다고 해서 그것을 알아야만 잘 짜여진 프로그램을 만들 수 있는 것은 아니다. 그리고 컴퓨터의 속도가 매우 빨라지고 보편화된 현대에는 고도로 추상화되고 생산성이 높은 언어에 대한 수요가 매우 크기 때문에, 다른 언어를 먼저 공부하는 것도 나쁘지 않은 선택이다.[* 최근 들어 많은 대학의 컴퓨터공학과에서 1학년 프로그래밍 입문 수업은 파이썬이나 자바 같은 비교적 쉬운 언어로 진행하고, 2학년 이후의 수업부터 C언어/C++로 넘어가는 편이다. 물론 1학년부터 바로 C언어/C++를 가르치는 학교도 있다...] 다소 어렵긴 어려운지, 대학교에서 C 언어를 공부하는 많은 학생들이 공부 [[C|공부 대상과 똑같은 학점]]을 받는 경우가 있는 모양. === C언어의 다음 언어? === B언어 기반으로 C언어가 탄생하면서 한때는 프로그래머 유머로 'C' 다음 언어가 과연 'D'일지 'P'일지[* B언어의 전신이 BCPL인 데서 따온 듯 하다.] 묻는 이야기가 있었지만 [[C++]] 같은 것도 나왔고, ANSI C, C99, ~~C0x~~ C11,[* 과거 새로운 표준이 200x년에 나올 줄 알고 C0x로 불렸으나, 2011년에 등장하여 C11이 됐다. C++ 역시 같은 이유로 C++0x로 불리다가 2011년에 등장하여 C++11이 됐다.] C18 등으로 가지를 뻗으며 진화 중인 현재의 C언어에게는 이미 과거의 이야기가 되어버렸다.[* 이들은 다른 언어가 아니라 버전이 다르다.] 사실 '''[[D언어|D]]'''라는 프로그래밍 언어도 있기는 있다. ~~ Birth와 Death 사이의 C언어 ~~ 벨 연구소가 아닌 [[http://www.digitalmars.com/|디지털 마르스]](Digital Mars)에서 만든 것이기는 하지만. C++와의 문법적인 호환성은 없지만 C++의 단점을 보완하면서 고생산성을 추구하는 하이 레벨 언어들의 특성들을 반영한 네이티브 컴파일 언어라 사실상 C++의 리엔지니어링 버전처럼 취급하고 있다. [[ABA Games]]의 게임들 대부분도 D언어로 만든 것이다. 잘 모르는 사실이지만 1997년에 등장한 [[https://en.wikipedia.org/wiki/E_(programming_language)|E]]라는 프로그래밍 언어도 있다. 등장한 순서만 따지면 2001년 12월에 등장해서 2007년에 정식판이 나온 D언어보다 훨씬 먼저 나온 셈. 그 외에 단일 영문자 이름을 지닌 프로그래밍 언어는 [[A(프로그래밍 언어)|A]], [[https://en.wikipedia.org/wiki/F_(programming_language)|F]], [[https://en.wikipedia.org/wiki/G_programming_language|G]], [[https://en.wikipedia.org/wiki/J_(programming_language)|J]], [[https://en.wikipedia.org/wiki/K_(programming_language)|K]], [[https://en.wikipedia.org/wiki/P_(programming_language)|P]], [[https://en.wikipedia.org/wiki/Q_(disambiguation)#Computing_and_computer_games|Q]], [[R(프로그래밍 언어)|R]], [[https://en.wikipedia.org/wiki/S_(programming_language)|S]], [[https://en.wikipedia.org/wiki/T_(programming_language)|T]], [[https://vlang.io/|V]], [[https://en.wikipedia.org/wiki/Z_notation|Z]]가 있다. === C언어와 '++', '#' === C언어의 문법으로 나오는 ++는 초기화된 변수의 값을 1 증가시켜 대입하는 연산자이다. 다시 말해 [[C++]]에서 ++은 C를 1 증가시켜 대입했다는 말. [[C\#]]에서 #은 ++++이다. (++이 위 아래로 두 개) 또한 C♯, 그러니깐 음악에서도 의미를 따왔다. ++와 반대로 1을 감소시키는 연산자 \-\-를 이름에 사용한 C\-\-라는 언어도 존재하는데 보다 고수준 언어의 컴파일러가 중간 언어로 생성하는 것을 목적으로 한 저수준 언어로, 주로 [[Haskell]]과 같은 함수형 언어들의 컴파일러가 이 C--를 사용한다. === Write in C === C언어와 관련해서 다음과 같은 노래도 있다. 참고로 다음 노래는 [[비틀즈]]의 [[Let It Be]]를 패러디한 것. [youtube(XHosLhPEN3k)] >When I find my code in tons of trouble >내가 짠 프로그램에 문제가 가득하단 걸 알았을 때 >friends and colleagues come to me, >친구와 동료들이 다가와 >speaking words of wisdom… >슬기로운 말을 해주었네 >…"write in C" >"C언어로 짜" > >And as the deadline fast approaches, >마감은 빠르게 다가오는데 >and bugs are all that I can see >버그밖에 보이지 않아 >Somewhere someone whispers: >어디선가 누군가가 속삭였지 >"Write in C" >"C언어로 짜" > >Write in C, Write in C, Write in C, Write in C, >C언어로 짜, C언어로 짜, C언어로 짜, C언어로 짜 >LOGO's dead and burried, >[[https://ko.wikipedia.org/wiki/%EB%A1%9C%EA%B3%A0_%28%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%B0%8D_%EC%96%B8%EC%96%B4%29|LOGO]]는 이미 죽어서 묻혀버렸어 >Write in C >C언어로 짜 > >I used to write a lot of FORTRAN >예전엔 [[포트란]]으로 많이 짰었어 >For science it worked flawlessly >수식 계산에선 나무랄 데 없었지만 >Try using it for Grahpics! >포트란으로 그래픽을 해 보라고! >Write in C! >C언어로 짜 > >And if you've just spent nearly 30 hours >[[어셈블리어|어셈블리]] 디버깅을 >debugging some assembly >30시간 정도 해 봤었다면 >Soon you will be glad to >금방 고마움을 느낄 거야 >write in C >C언어로 짜 > >Write in C, Write in C, Write in C, Write in C. >C언어로 짜, C언어로 짜, C언어로 짜, C언어로 짜 >BASIC's not the answer, >[[BASIC|베이식]]으론 해결이 안 돼 >Write in C. >C언어로 짜 > >Write in C, Write in C, Write in C, Write in C. >C언어로 짜, C언어로 짜, C언어로 짜, C언어로 짜 >PASCAL won't quite cut it, >[[파스칼(프로그래밍 언어)|파스칼]]로는 부족한 걸 >Write in C! >C언어로 짜 이 노래에 대한 또 다른 패러디로, [[Go(프로그래밍 언어)|Go]] 버전인 [[Go(프로그래밍 언어)#여담|Write in Go]]도 존재한다. == 둘러보기 == [include(틀:컴퓨터공학)] [include(틀:프로그래밍 언어)] [include(틀:TIOBE/C)] == 관련 문서 == * [[C++]] * [[Python]] * [[Java]] * [[C\#]] * [[Zig]] * [[인라인 함수]] * [[참조에 의한 호출]] * [[절차적 프로그래밍]] * [[명령형 프로그래밍]] * [[구조적 프로그래밍]] * -- [[김대호(e스포츠)#s-7.1|김대호]] -- == 관련 커뮤니티 == * [[https://gall.dcinside.com/tcpl/|C언어 마이너 갤러리]] * [[https://cafe.naver.com/cafec/|C언어를 배우자(네이버 카페))]] [[분류:절차적 언어]][[분류:1972년 출시]][[분류:미국의 발명품]]