C 프로그래밍 언어가 여전히 지배하는 이유

다른 어떤 것, 특히 컴퓨터 기술보다 더 잘 작동하지 않는 한 50 년 동안 어떤 기술도 유지되지 않습니다. C 프로그래밍 언어는 1972 년부터 살아 있고 시작되었으며, 여전히 소프트웨어 정의 세계의 기본 구성 요소 중 하나로 군림하고 있습니다.

그러나 때로는 사람들이 그것을 대체하지 못했기 때문에 기술이 남아 있습니다. 지난 수십 년 동안 수십 개의 다른 언어가 등장했습니다. 일부는 C의 우위에 도전하기 위해 명시 적으로 설계되었으며, 일부는 인기의 부산물로 C에서 멀어졌습니다.

C가 교체해야한다고 주장하는 것은 어렵지 않습니다. 프로그래밍 언어 연구 및 소프트웨어 개발 관행은 모두 C의 방식보다 일을 수행하는 데 훨씬 더 나은 방법이 있음을 암시합니다. 그러나 C는 수십 년의 연구와 개발을 통해 동일하게 유지됩니다. 성능, 베어 메탈 호환성 또는 편재성 측면에서 다른 언어를 능가 할 수있는 언어는 거의 없습니다. 그래도 C가 2018 년에 유명 언어 경쟁에서 어떻게 경쟁하는지 볼 가치가 있습니다.

C 대 C ++

당연히 C는 이름 자체에서 알 수 있듯이 C의 확장으로 만들어진 언어 인 C ++와 가장 일반적으로 비교됩니다. C ++와 C의 차이점은 누구에게 요청 하느냐에 따라 광범위하거나 과도 하다는 특징이있을 수 있습니다  .

구문과 접근 방식에서 여전히 C와 비슷하지만 C ++는 C에서 기본적으로 사용할 수없는 많은 유용한 기능 (네임 스페이스, 템플릿, 예외, 자동 메모리 관리 등)을 제공합니다. 최고 수준의 성능을 요구하는 프로젝트 (데이터베이스, 기계 학습 시스템)는 이러한 기능을 사용하여 시스템에서 모든 성능 저하를 가져 오는 C ++로 자주 작성됩니다.

또한 C ++는 C보다 훨씬 더 공격적으로 확장되고 있습니다. 곧 출시 될 C ++ 20은 모듈, 코 루틴, 동기화 라이브러리 및 개념을 포함하여 테이블에 훨씬 더 많은 것을 제공하여 템플릿을 더 쉽게 사용할 수 있도록합니다. C 표준의 최신 개정판은 추가 기능이 거의 없으며 이전 버전과의 호환성 유지에 중점을 둡니다.

문제는 C ++의 모든 플러스가 마이너스로 작동 할 수 있다는 것입니다. 큰 것. 사용하는 C ++ 기능이 많을수록 도입이 더 복잡해지고 결과를 길들이기가 더 어려워집니다. C ++의 하위 집합에 국한된 개발자는 최악의 함정과 과잉을 피할 수 있습니다. 그러나 일부 상점은 C ++ 복잡성을 모두 방지하기를 원합니다. C를 고수하면 개발자는 해당 하위 집합에 국한됩니다. 예를 들어 Linux 커널 개발 팀은 C ++를 피합니다.

C ++보다 C를 선택하는 것은 강제적 인 미니멀리즘을 수용하여 C ++ 과잉과 얽히게하는 일을 피할 수있는 방법입니다. 물론 C ++에는 좋은 이유가있는 풍부한 고급 기능이 있습니다. 그러나 미니멀리즘이 현재와 미래의 프로젝트와 프로젝트 팀에 더 적합하다면 C가 더 의미가 있습니다.

C 대 자바

수십 년이 지난 후에도 Java는 엔터프라이즈 소프트웨어 개발의 필수 요소이며 일반적으로 개발의 필수 요소입니다. 대부분의 Apache Software Foundation 프로젝트를 포함하여 가장 중요한 엔터프라이즈 소프트웨어 프로젝트의 대부분은 Java로 작성되었으며 Java는 엔터프라이즈 급 요구 사항이있는 새 프로젝트를 개발하기위한 실행 가능한 언어로 남아 있습니다.

Java 구문은 C 및 C ++에서 많은 것을 차용합니다. 그러나 C와 달리 Java는 기본적으로 네이티브 코드로 컴파일되지 않습니다. 대신 Java 런타임 환경 인 JVM, JIT (just-in-time)가 대상 환경에서 실행되도록 Java 코드를 컴파일합니다. 적절한 상황에서 JITted Java 코드는 C의 성능에 접근하거나이를 능가 할 수 있습니다.

Java의 "한 번 작성하면 어디에서나 실행"철학을 통해 Java 프로그램을 대상 아키텍처에 대해 비교적 약간의 조정만으로 실행할 수 있습니다. 대조적으로, C가 많은 아키텍처로 포팅되었지만 특정 C 프로그램이 Windows 대 Linux에서 제대로 실행 되려면 여전히 사용자 정의가 필요할 수 있습니다.

이러한 이식성과 강력한 성능의 조합은 소프트웨어 라이브러리 및 프레임 워크의 방대한 에코 시스템과 함께 Java를 엔터프라이즈 애플리케이션 구축을위한 언어 및 런타임으로 만듭니다.

Java가 C에 미치지 못하는 곳은 Java가 경쟁 할 수없는 영역입니다. 금속 가까이에서 실행하거나 하드웨어와 직접 작업하는 것입니다. C 코드는 프로세스에 의해 직접 실행되는 기계 코드로 컴파일됩니다. Java는 JVM 인터프리터가 기계 코드로 변환하는 중간 코드 인 바이트 코드로 컴파일됩니다. 또한 Java의 자동 메모리 관리는 대부분의 상황에서 축복이지만 C는 제한된 메모리 자원을 최적으로 사용해야하는 프로그램에 더 적합합니다.

즉, 속도면에서 Java가 C에 가까워 질 수있는 영역이 있습니다. JVM의 JIT 엔진은 프로그램 동작을 기반으로 런타임에 루틴을 최적화하여 사전 컴파일 된 C로는 불가능한 많은 최적화 클래스를 허용합니다. Java 런타임은 메모리 관리를 자동화하지만 일부 새로운 애플리케이션은이를 해결합니다. 예를 들어 Apache Spark는 JVM을 우회하는 사용자 지정 메모리 관리 코드를 사용하여 부분적으로 메모리 내 처리를 최적화합니다.

C 대 C # 및 .Net

도입 된 지 거의 20 년이 지난 지금 C #과 .Net Framework는 엔터프라이즈 소프트웨어 세계의 주요 부분으로 남아 있습니다. C #과 .Net은 Java (관리 코드 컴파일러 시스템 및 범용 런타임)에 대한 Microsoft의 반응이며 C와 Java 간의 수많은 비교도 C와 C # /. Net을 유지한다고합니다.

Java (및 어느 정도 Python)와 마찬가지로 .Net은 다양한 플랫폼과 방대한 통합 소프트웨어 에코 시스템에서 이식성을 제공합니다. .Net 세계에서 얼마나 많은 엔터프라이즈 지향 개발이 이루어지고 있는지를 감안할 때 이것은 작은 이점이 아닙니다. C # 또는 다른 .Net 언어로 프로그램을 개발할 때 .Net 런타임 용으로 작성된 다양한 도구 및 라이브러리에 그릴 수 있습니다. 

Java와 유사한 또 다른 .NET 장점은 JIT 최적화입니다. C # 및 .Net 프로그램은 C에 따라 미리 컴파일 할 수 있지만 주로 .Net 런타임에 의해 Just-In-Time 컴파일되고 런타임 정보로 최적화됩니다. JIT 컴파일은 C에서 수행 할 수없는 실행중인 .Net 프로그램에 대한 모든 종류의 내부 최적화를 허용합니다.

C와 마찬가지로 C # 및 .Net은 메모리에 직접 액세스하기위한 다양한 메커니즘을 제공합니다. 힙, 스택 및 관리되지 않는 시스템 메모리는 모두 .Net API 및 개체를 통해 액세스 할 수 있습니다. 그리고 개발자는 unsafe.Net 의 모드를 사용하여 더 큰 성능을 얻을 수 있습니다 .

하지만이 중 어느 것도 무료로 제공되지 않습니다. 관리되는 개체와 unsafe개체는 임의로 교환 할 수 없으며 이들 간의 마샬링에는 성능 비용이 발생합니다. 따라서 .Net 응용 프로그램의 성능을 최대화한다는 것은 관리 대상 개체와 관리되지 않는 개체 간의 이동을 최소화하는 것을 의미합니다.

관리되는 메모리와 관리되지 않는 메모리에 대한 패널티를 지불 할 여유가 없거나 .Net 런타임이 대상 환경 (예 : 커널 공간)에 적합하지 않거나 전혀 사용할 수없는 경우 C가됩니다. 필요한 것. 그리고 C # 및 .Net과 달리 C는 기본적으로 직접 메모리 액세스를 잠금 해제합니다. 

C 대 Go

Go 구문은 구분자 인 중괄호, 세미콜론으로 끝나는 명령문 등 C에 많은 영향을 미칩니다. C에 능숙한 개발자는 네임 스페이스 및 패키지 관리와 같은 새로운 Go 기능을 고려하더라도 일반적으로 큰 어려움없이 바로 Go로 이동할 수 있습니다.

가독성이 뛰어난 코드는 Go의 디자인 목표 중 하나였습니다. 개발자가 Go 프로젝트를 쉽게 익히고 짧은 시간 내에 코드베이스에 능숙 해 지도록합니다. C 코드베이스는 #ifdef프로젝트와 주어진 팀 모두에 특정한 매크로와 s 의 둥지로 바뀌기 쉬우므로 그 루크하기 어려울 수 있습니다 . Go의 구문과 내장 된 코드 서식 및 프로젝트 관리 도구는 이러한 종류의 제도적 문제를 방지하기위한 것입니다.

Go는 또한 고 루틴 및 채널과 같은 추가 기능, 구성 요소 간 동시성 및 메시지 전달을 처리하기위한 언어 수준 도구를 제공합니다. C는 이러한 것들을 손으로 말거나 외부 라이브러리에서 제공해야하지만 Go는 이러한 것들을 즉시 제공하므로이를 필요로하는 소프트웨어를 훨씬 쉽게 구성 할 수 있습니다.

Go가 C와 가장 다른 점은 메모리 관리에 있습니다. Go 객체는 기본적으로 자동으로 관리되고 가비지 수집됩니다. 대부분의 프로그래밍 작업에서 이것은 매우 편리합니다. 그러나 결정 론적 메모리 처리가 필요한 모든 프로그램은 쓰기가 더 어렵다는 의미이기도합니다.

Go에는 unsafe유형을 사용하여 임의의 메모리를 읽고 쓰는 것과 같은 Go의 유형 처리 안전성을 우회하기위한 패키지 가 포함되어 Pointer있습니다. 그러나 이와 unsafe함께 작성된 프로그램은 "이동이 불가능할 수 있으며 Go 1 호환성 지침에 의해 보호되지 않을 수 있습니다."라는 경고와 함께 제공됩니다.

Go는 이러한 세분화 된 조작이 거의 필요하지 않기 때문에 명령 줄 유틸리티 및 네트워크 서비스와 같은 프로그램을 구축하는 데 적합합니다. 그러나 저수준 장치 드라이버, 커널 공간 운영 체제 구성 요소 및 메모리 레이아웃 및 관리에 대한 정확한 제어가 필요한 기타 작업은 C에서 가장 잘 생성됩니다.

C 대 Rust

어떤면에서 Rust는 C와 C ++에 의해 생성 된 메모리 관리 수수께끼와 이러한 언어의 다른 많은 단점에 대한 응답입니다. Rust는 네이티브 머신 코드로 컴파일되므로 성능면에서 C와 동등하게 간주됩니다. 하지만 기본적으로 메모리 안전은 Rust의 주요 판매 포인트입니다.

Rust의 구문과 컴파일 규칙은 개발자가 일반적인 메모리 관리 실수를 피하는 데 도움이됩니다. 프로그램에 Rust 구문을 넘는 메모리 관리 문제가있는 경우 컴파일되지 않습니다. 언어를 처음 접하는 사람들, 특히 그러한 버그에 대한 충분한 공간을 제공하는 C와 같은 언어에서, Rust 교육의 첫 번째 단계에서 컴파일러를 달래는 방법을 배우는 데 소비합니다. 그러나 Rust 지지자들은 이러한 단기적 고통이 장기적인 보상을 가지고 있다고 주장합니다. 즉, 속도를 희생하지 않는 안전한 코드입니다.

Rust는 또한 도구로 C를 향상시킵니다. 프로젝트 및 구성 요소 관리는 Go와 마찬가지로 기본적으로 Rust와 함께 제공되는 도구 모음의 일부입니다. 패키지를 관리하고, 프로젝트 폴더를 구성하고, C에서 기껏해야 임시적인 다른 많은 것들을 처리하는 데 권장되는 기본 방법이 있으며 각 프로젝트와 팀은 각기 다르게 처리합니다.

그래도 Rust에서 장점으로 선전되는 것은 C 개발자에게는 하나가 아닌 것 같습니다. Rust의 컴파일 타임 안전 기능은 비활성화 할 수 없습니다. 따라서 가장 사소한 Rust 프로그램이라도 Rust의 메모리 안전 제한을 준수해야합니다. C는 기본적으로 덜 안전 할 수 있지만 필요한 경우 훨씬 더 유연하고 관대합니다.

또 다른 가능한 단점은 Rust 언어의 크기입니다. C는 표준 라이브러리를 고려하더라도 비교적 적은 기능을 가지고 있습니다. Rust 기능 세트는 넓고 계속해서 성장하고 있습니다. C ++와 마찬가지로, Rust 기능 세트가 클수록 더 많은 힘이 있지만 더 복잡해집니다. C는 더 작은 언어이지만 정신적으로 모델링하기가 훨씬 더 쉽기 때문에 Rust가 과잉 인 프로젝트에 더 적합 할 것입니다.

C 대 Python

요즘에는 소프트웨어 개발에 대해 이야기 할 때마다 Python이 항상 대화에 참여하는 것처럼 보입니다. 결국 Python은 "모든면에서 두 번째로 좋은 언어"이며 수천 개의 타사 라이브러리를 사용할 수있는 가장 다재다능한 언어 중 하나입니다.

Python이 강조하는 것은 C와 가장 다른 점은 실행 속도보다 개발 속도를 선호한다는 것입니다. C와 같은 다른 언어로 통합하는 데 1 시간이 걸릴 수있는 프로그램은 몇 분 안에 Python으로 조립 될 수 있습니다. 반대로이 프로그램은 C에서 실행하는 데 몇 초가 걸릴 수 있지만 Python에서 실행되는 데 1 분 정도 걸립니다. (좋은 경험 법칙 : Python 프로그램은 일반적으로 C 프로그램보다 훨씬 느리게 실행됩니다.) 그러나 현대 하드웨어에서 많은 작업을 수행하는 경우 Python은 충분히 빠르며 이것이 핵심입니다.

또 다른 주요 차이점은 메모리 관리입니다. Python 프로그램은 Python 런타임에 의해 완전히 메모리 관리되므로 개발자는 메모리 할당 및 해제에 대해 걱정할 필요가 없습니다. 그러나 여기서도 개발자의 편의성은 런타임 성능의 대가로 따릅니다. C 프로그램을 작성하려면 메모리 관리에 세심한주의가 필요하지만 그 결과 프로그램은 종종 순수한 기계 속도의 표준이됩니다.

하지만 스킨 아래에서 Python과 C는 깊은 연결을 공유합니다. 참조 Python 런타임은 C로 작성됩니다.이를 통해 Python 프로그램은 C 및 C ++로 작성된 라이브러리를 래핑 할 수 있습니다. 머신 러닝과 같은 타사 라이브러리의 Python 생태계의 상당 부분은 핵심에 C 코드를 가지고 있습니다.

개발 속도가 실행 속도보다 중요하고 프로그램의 대부분의 성능 부분을 독립형 구성 요소로 격리 할 수 ​​있다면 (코드 전체에 분산되는 것과는 반대로) 순수 Python 또는 Python과 C 라이브러리의 혼합이 C 단독보다 나은 선택입니다. 그렇지 않으면 C가 여전히 지배합니다.