사람들이 왜 그렇게 위험한 C를 사용합니까?


132

C를 배우는 것을 고려하고 있습니다.

그러나 사람들이 왜 '위험하게'사용될 수 있다면 C (또는 C ++)를 사용합니까?

위험하다는 것은 포인터와 다른 유사한 것들을 의미합니다.

스택 오버플로 질문처럼 gets 함수가 왜 그렇게 사용되어서는 안 되는가? . 프로그래머가 Java 나 Python 또는 Visual Basic과 같은 다른 컴파일 된 언어를 사용하지 않는 이유는 무엇입니까?


152
요리사가 '위험하게'사용할 수 있다면 왜 칼을 사용합니까?
oerkelens

78
큰 힘에는 큰 책임이 따른다.
Pieter B

10
조 블로우?
Matthew James Briggs

4
C가 선택의 언어가되었을 때 "Back In The Day"가 있기 때문에 우리는 그와 같은 것을 처리 할 수있을 것으로 기대되었습니다. 오늘의 프로세서가 너무 느려서 해석되거나 바이트 코드 언어가 너무 느 렸습니다. (오늘 저는 2GHz 이상의 멀티 코어 CPU4GB 의 메모리를 갖춘 저가형 데스크탑 PC를 279 달러에 Dell에서 구입할 수 있습니다. 4MHz PC 를 사용하는 사람에게 이것이 얼마나 놀라운 지 전혀 알 수 없습니다. 640 킬로바이트 의 메모리로 인해 행복했습니다 ...). 그것을 직면-무어의 법칙이 이겼다. 경기. 위에!
Bob Jarvis 2016 년

6
@ 밥 자비스 : 게임이 끝나지 않았습니다. 2 + GHz, 4GB PC 또는 그 문제에 대해 최신 CUDA GPU를 갖춘 수백 개의 4GHz PC 클러스터 또는 그 밖의 속도가 빠르다고 생각되면 충분한 문제를 해결하지 않고 있습니다. :-)
jamesqf 2016 년

답변:


246
  1. C는 당신이 생각하고있는 다른 많은 언어보다 우선합니다. 프로그래밍을 "새퍼"로 만드는 방법에 대해 우리가 알고있는 많은 것은 C와 같은 언어에 대한 경험에서 비롯됩니다.

  2. C 이후로 나온 더 안전한 언어는 더 큰 런타임, 더 복잡한 기능 세트 및 / 또는 목표를 달성하기 위해 가상 머신에 의존합니다. 결과적으로 C는 모든 대중 / 주류 언어 중에서 "가장 낮은 공통 분모"로 남아 있습니다.

    • C는 상대적으로 작고 가장 약한 환경에서도 적절하게 수행 될 가능성이 높기 때문에 구현하기가 훨씬 쉬운 언어입니다. 따라서 자체 컴파일러 및 기타 도구를 개발해야하는 많은 임베디드 시스템에서 함수형 컴파일러를 제공 할 가능성이 높습니다 C를 위해

    • C는 매우 작고 단순하기 때문에 다른 프로그래밍 언어는 C와 유사한 API를 사용하여 서로 통신하는 경향이 있습니다. 이것이 우리 대부분이 래퍼를 통해서만 상호 작용하더라도 C가 진정으로 죽지 않는 주된 이유 일 것입니다.

  3. C 및 C ++에서 개선하려고하는 많은 "safer"언어는 프로그램의 메모리 사용 및 런타임 동작을 거의 완전히 제어 할 수있는 "시스템 언어"가 아닙니다. 요즘 점점 더 많은 응용 프로그램이 단순히 그 수준의 제어를 필요로하지 않는 것이 사실이지만, 항상 필요한 몇 가지 사례가있을 것입니다 (특히 가상 머신 및 브라우저에서 우리의 나머지).

    현재 C 또는 C ++보다 안전한 몇 가지 시스템 프로그래밍 언어 (Rust, Nim, D, ...)가 있습니다. 그들은 후 시점의 이점을 가지고 있으며, 대부분의 경우 이러한 정밀한 제어가 필요하지 않다는 것을 알고 있으므로 실제로 필요할 때 전환 할 수있는 안전하지 않은 후크 / 모드가 몇 개있는 일반적으로 안전한 인터페이스를 제공합니다.

  4. C 내에서도 실제로 나타나는 교활한 버그의 수를 크게 줄이는 경향이있는 많은 규칙과 지침을 배웠습니다. 기존 코드를 너무 많이 깨뜨릴 수 있기 때문에 이러한 규칙을 소급 적용하여 표준을 적용하는 것은 일반적으로 불가능하지만, 컴파일러 경고, 린터 및 기타 정적 분석 도구를 사용하여 이러한 종류의 쉽게 예방할 수있는 문제를 감지하는 것이 일반적입니다. 이러한 도구를 통과하는 C 프로그램의 하위 집합은 이미 "정확한 C"보다 훨씬 안전하며 오늘날 유능한 C 프로그래머는 일부 프로그램을 사용하게됩니다.


또한, 난독 화 된 C 콘테스트 처럼 재미있는 난독 화 된 Java 콘테스트를 만들 수 없습니다 .


7
"가장 낮은 공통 분모"는 소리가 나지 않습니다. 나는 훨씬 더 무거운 언어들과 달리 C는 필요없는 톤의 추가 수하물을 강요하지 않으며 필요한 물건을 구현할 수있는 매우 빠른 기반을 제공한다고 말합니다. 그게 무슨 뜻입니까?
underscore_d

9
"실제로 다른 언어를 사용할 수는 없습니다.": 실제로 많은 새로운 언어 (Rust, Nim, D, ...)가 시도합니다. 이것은 기본적으로이 수준의 제어가 절대적으로 필요한 경우 "안전하지 않은"언어의 몇 가지 "안전하지 않은"기본 요소를 일치시키는 것으로 요약됩니다. 그러나 C와 C ++에서 축적 된 지식을 기반으로하는 모든 것들이 있으므로 C와 C ++가 개발 될 때 다른 언어없이 하나를 가질 수 없으며 오늘날에는 언어를 분리하려는 언어가 있다고 할 수 있습니다. "안전하지 않은"비트이지만 아직 따라 잡지 않았습니다.
Matthieu M.

6
1) 유효한 포인트가 아닙니다! C는 이러한 의미에서 "안전한"언어 인 Algol 68의 기능을 사용했습니다. 저자는 그러한 언어에 대해 알고있었습니다. 다른 점은 훌륭합니다.
reinierpost

4
@MatthieuM. Microsoft Research도 살펴볼 수 있습니다. 지난 10 ~ 2 년 동안 특정 실제 워크로드에 대해 관리되지 않는 동일한 OS보다 더 빠르거나 (사실-대부분의 연구 OS의 주요 목표는 속도가 아니라 안전) 일부를 포함하여 몇 개의 관리 형 OS를 생산했습니다. . 속도 향상은 대부분 안전 제약으로 인해 발생합니다. 정적 및 동적 실행 파일 검사는 관리되지 않는 코드에서는 사용할 수없는 최적화를 허용합니다. 전체적으로 볼 부분이 꽤 있으며 소스도 포함되어 있습니다;)
Luaan

3
@Luaan : 미도리는 정말 멋져요. 나는 항상 Joe의 블로그 기사를 기대하고 있습니다.
Matthieu M.

41

첫째, C는 시스템 프로그래밍 언어입니다. 예를 들어, Java 가상 머신 또는 Python 인터프리터를 작성하는 경우이를 작성하려면 시스템 프로그래밍 언어가 필요합니다.

둘째, C는 Java 및 Python과 같은 언어가 제공하지 않는 성능을 제공합니다. 일반적으로 Java 및 Python의 고성능 컴퓨팅은 C와 같은 고성능 언어로 작성된 라이브러리를 사용하여 많은 작업을 수행합니다.

셋째, C는 Java 및 Python과 같은 언어보다 설치 공간이 훨씬 작습니다. 이를 통해 임베디드 시스템에 사용할 수 있으며 Java 및 Python과 같은 언어의 대규모 런타임 환경 및 메모리 요구를 지원하는 데 필요한 리소스가 없을 수 있습니다.


"시스템 프로그래밍 언어"는 산업 시스템을 구축하기에 적합한 언어입니다. Java와 Python은 시스템 프로그래밍 언어가 아닙니다. "정확하게 시스템 프로그래밍 언어를 만드는 것"은이 질문의 범위를 벗어나지 만, 시스템 프로그래밍 언어는 기본 플랫폼으로 작업하기위한 지원을 제공해야합니다.

반면에 (댓글에 대한 응답으로) 시스템 프로그래밍 언어는 자체 호스팅 일 필요 는 없습니다 . 이 문제는 PyPy를 사용할 때 원래 질문에 "사람들이 C를 사용하는 이유"와 첫 번째 의견에 "왜 C와 같은 언어가 필요한지"가 묻고 PyPy 실제로 C를 사용한다는 점을 지적했기 때문에 발생했습니다. 원래 질문과 관련이 있었지만 불행히도 (그리고 혼란스럽게도) "자기 호스팅"은 실제로이 답변과 관련이 없습니다. 내가 가져 와서 미안해

요약하자면, Java와 Python은 기본 구현이 해석되거나 기본적으로 컴파일 된 구현이 자체 호스팅되지 않기 때문에 기본 플랫폼으로 작업하는 데 필요한 지원을 제공하지 않기 때문에 시스템 프로그래밍에 적합하지 않습니다.


19
"Java 가상 머신 또는 Python 인터프리터를 작성하려면이를 작성할 수있는 시스템 프로그래밍 언어가 필요합니다." 어? PyPy를 어떻게 설명합니까? 컴파일러, 인터프리터 또는 가상 머신을 작성하려면 왜 C와 같은 언어가 필요합니까?
Vincent Savard 2016 년

10
"Java 가상 머신 또는 Python 인터프리터를 작성하는 경우이를 작성하려면 시스템 프로그래밍 언어가 필요합니다."라고 말했을 때 Java 가상 머신 또는 Python 인터프리터를 작성하려면 시스템 프로그래밍 언어가 필요하다고 생각합니다. PyPy가 만족스럽지 않으면 Haskell로 작성된 해석기 또는 컴파일러를 볼 수도 있습니다. 또는 귀하의 주장을 뒷받침하는 참조를 추가하십시오.
Vincent Savard 2016 년

16
거북이 끝났어도 PyPy와 같은 것은 다른 언어로 작성된 파이썬 해석기가 없으면 존재할 수 없었습니다.
Blrfl

18
@ Birfl 그러나 그것은 실제로 많은 말을하지 않습니다. C는 어셈블리 컴파일러 없이는 작성할 수 없었으며이를 구현하는 하드웨어 없이는 어셈블리를 작성할 수 없습니다.
gardenhead

11
C 컴파일러가 어딘가에 관여하여 PyPy가 "시스템 프로그래밍 언어"가 아닌 경우 어셈블러가 어딘가에 사용되기 때문에 C는 시스템 프로그래밍 언어가 아닙니다. 실제로 요즘 C를 다른 언어로 번역하는 것이 인기가 있습니까? 예 : LLVM

30

또 다른 답변을 추가하여 죄송하지만 기존 답변 중 첫 번째 문장을 직접 언급하는 것은 아닙니다.

'C 학습을 고려하고 있습니다'

왜? C가 오늘날 일반적으로 사용하는 것들 (예 : 장치 드라이버, VM, 게임 엔진, 미디어 라이브러리, 임베디드 시스템, OS 커널)을 원하십니까?

그렇다면 관심있는 사람에 따라 C 또는 C ++를 배우십시오. 배우고 싶습니까? 고급 언어가 무엇을하고 있는지에 대해 더 깊이 이해하고 싶습니까?

그런 다음 안전 문제를 언급합니다. 고급 언어의 코드 예제가 프로덕션 준비없이 요점을 제공 할 수있는 것과 같은 방식으로 안전한 C에 대한 깊은 이해가 필요하지 않습니다 .

요점을 얻으려면 C 코드를 작성하십시오. 그런 다음 선반에 다시 넣으십시오. 프로덕션 C 코드 를 작성하지 않으려면 안전에 대해 너무 걱정하지 마십시오 .


2
실제 질문으로 보이는 것에 대한 훌륭한 답변! C / C ++ 및 "safer"언어를 이해하는 가장 좋은 방법은 간단한 데이터베이스 엔진과 같은 것을 작성하는 것입니다. 당신은 당신이 시도하는 각각의 접근법에 대해 좋은 느낌을 갖게 될 것이며, 그것이 당신을 이끄는 곳을 볼 것입니다. 어느 쪽이 자연스럽게 느껴지는 지 알 수 있으며 자연적인 접근 방식이 실패한 곳을 찾을 수 있습니다 (예 : C에서 원시 데이터를 "직렬화"하는 것이 매우 쉽습니다. 데이터 만 쓰십시오!); 그러나 결과는 이식성이 없으므로 제한적으로 사용될 수 있습니다). 대부분의 문제가 발생하기 어려울 수 있으므로 안전을 이해하는 것은 까다 롭습니다.
Luaan

1
@Luaan은 포인터를 사용하여 문자열을 복사하는 방법을 배우면 안전하게 수행하는 방법을 배우는 것이 또 다른 수준이며 목표에 따라 불필요 한 목표입니다.
Jared Smith

2
이것은 실제로 질문이 아니 었습니다. 그러나 그것은 분열에 도움이되었다. 나는 그것을하기로 결정했다. 나는 모든 것의 내부 작업에 대한 자세한 내용을 기꺼이 배울 것입니다. 그리고 저는 프로그래밍을 좋아합니다. 이렇게하면 컴퓨터의 내부 작동을 더 잘 이해하기를 바랍니다. 그냥 재미입니다.
Tristan

10
나는 마지막 문장에 동의하지 않습니다. 나쁜 습관을 들이기 전에 어떻게해야하는지 배우십시오.
glglgl

2
@glglgl IDK, 웹에서 JavaScript 스 니펫을 읽거나 쓰면 생산 준비가되지 않았다는 것을 이해하여 예외 처리가 없으며 O (n ^ 2) 등이 될 수 있습니다. 그 점을 극복하기 위해 필요합니다. 프로덕션 코드에는 모두 필요합니다. 왜 다른가요? 나는 내 자신의 교화를 위해 순진한 C를 쓸 수 있으며 , 그것을 지적 하고 싶다면 더 많은 일을해야한다는 것을 지적 합니다.
Jared Smith

14

이것은 많은 답변이있는 거대한 질문이지만 짧은 버전은 각 프로그래밍 언어가 다른 상황에 특화되어 있다는 것입니다. 예를 들어, 웹용 JavaScript, 저수준 물건 용 C, Windows 용 C # 등을 선택할 수 있습니다. 프로그래밍을 알고 나면 어떤 프로그래밍 언어를 선택해야하는지 결정하는 데 도움이됩니다.

Java / Python보다 C / C ++ 인 마지막 요점을 해결하기 위해 종종 속도가 떨어집니다. 게임을 만들고 있으며 최근 Java / C #에서 게임을 실행하기에 충분한 속도에 도달했습니다. 결국 게임을 초당 60 프레임으로 실행하고 게임을 많이 수행하려면 (렌더링이 특히 비쌉니다) 가능한 한 빨리 실행하려면 코드가 필요합니다. 파이썬 / 자바 / C # / 많은 사람들이 메모리 및 가비지 수집과 같은 C / C ++가하지 않는 모든 지루한 작업을 처리하는 추가 소프트웨어 계층 인 "인터프리터"에서 실행됩니다. 추가 오버 헤드로 인해 속도가 느려지므로 거의 모든 대형 게임이 지난 10 년 동안 C 또는 C ++에서 수행되었습니다. Unity 게임 엔진은 C # *을 사용하고 Minecraft는 Java를 사용하지만 예외는 예외입니다. 예외는 예외입니다. 일반적으로

* 유니티조차도 모든 C #이 아니며, 그 중 상당 부분이 C ++이며 게임 코드에 C # 만 사용합니다.

편집 내가 이것을 게시 한 후 나타난 의견 중 일부에 답하기 위해 : 너무 지나치게 단순화하고 있었을 것입니다. 프로그래밍으로 대답은 간단하지 않습니다. C에 대한 인터프리터가 있으며 Javascript는 브라우저 외부에서 실행할 수 있으며 C #은 Mono 덕분에 거의 모든 항목에서 실행될 수 있습니다. 서로 다른 프로그래밍 언어는 서로 다른 도메인에 특화되어 있지만, 어떤 프로그래머는 어딘가에서 어떤 언어로 언어를 실행시키는 지 알아낼 것입니다. OP가 많은 프로그래밍을 알지 못하는 것처럼 보였으므로 (나의 가정, 잘못하면 미안합니다) 대답을 간단하게 유지하려고했습니다.

C #이 C ++만큼 빠르다는 의견은 거의 핵심 키워드입니다. 대학에 다닐 때 우리는 많은 게임 회사를 방문했고, 선생님 (연중 C #에서 C ++로 이사하도록 격려 해주신 교사)은 모든 회사의 프로그래머에게 C #이 아닌 C ++에 대한 이유를 물어 보았습니다. C #이 너무 느리다고 말했다. 일반적으로 실행 속도는 빠르지 만 가비지 수집기는 실행 시간을 제어 할 수 없기 때문에 성능을 저하시킬 수 있으며 권장 할 때 실행하지 않으려는 경우 무시할 권리가 있습니다. 고성능이 필요한 것이 필요한 경우에는 예측할 수없는 것을 원하지 않습니다.

내 "단순한 속도"의견에 응답하기 위해, C #의 속도 증가 중 상당 부분이 더 나은 하드웨어에서 비롯된 것이지만 .NET 프레임 워크 및 C # 컴파일러가 향상됨에 따라 속도가 약간 향상되었습니다.

"게임은 엔진과 같은 언어로 작성되었습니다"라는 의견에 따라 다릅니다. 일부는 있지만 많은 언어는 하이브리드 언어로 작성되었습니다. Unreal은 UnrealScript와 C ++를, Unity는 C # Javascript와 Boo를, C 또는 C ++로 작성된 많은 다른 엔진은 Python 또는 Lua를 스크립팅 언어로 사용합니다. 거기에 간단한 대답이 없습니다.

그리고 "게임이 200fps 또는 120fps로 실행되는지 걱정하는 사람"이라는 글을 읽었 기 때문에 평균 모니터가 화면을 새로 고치지 않기 때문에 CPU 시간을 낭비하고있을 것입니다. 빠른. 일부 고급형 및 최신형은 표준이지만 표준은 아닙니다 (아직 ...).

그리고 "수십 년 동안의 기술 무시"에 관해, 나는 여전히 20 대 초반에 있습니다. 따라서 거꾸로 외삽 할 때, 나는 더 나이가 많고 숙련 된 프로그래머들이 나에게 말한 것을 반향합니다. 분명히 이와 같은 사이트에서 경쟁 할 것이지만 고려할 가치가 있습니다.


4
" C # for any windows "-아, 그건 잘못된 것입니다. 그리고 당신은 예를 제공합니다. 통일. AFAIK 언어가 적응력이 좋기 때문에 C # API를 제공하도록 작성되지 않았습니다. 정말 잘 설계되었습니다. 그리고 나는 C ++을 더 좋아하지만 크레딧이 필요한 곳에서 크레딧을 받아야합니다. 어쩌면 C #과 .NET을 섞었습니까? 그들은 꽤 자주 어울립니다.
luk32

2
"유니티조차도 모든 C #이 아니고, 그 중 상당 부분이 C ++입니다"그리고? Unity 게임은 종종 C #을 광범위하게 사용하며 꽤 오랫동안 사용되었습니다. C #이 '최근에 속도에 도달하고있다'는 제안에는 더 많은 맥락이 필요하거나 수십 년간의 기술에 대해 눈을 멀게 할 위험이 있습니다.
NPSF3000

2
거의 모든 대형 게임은 사용한 엔진의 언어로 작성되었습니다. 복제해야 할 작업량이 너무 커서 다른 기술적 고려 사항도 고려할 가치가 없었습니다. 렌더링은 실제로 비싸지 만 요즘은 모두 셰이더로 작성되며 논리 루프의 언어는 관련이 없습니다.
피터 테일러

2
C #은 항상 JIT로 컴파일되었으며 (자바가 올바른 Java와 달리), 수행중인 작업을 알면 C ++과 매우 유사한 실행 속도를 얻을 수있었습니다. 그것은 2003 년입니다-최근에 고려할 것이 아닙니다. 원시 속도는 게임의 주된 문제가 아니며 (특히 GPU의 프로그래머블 쉐이더에서) C #과 같은 언어가 때때로 인기를 끌게하는 다른 요소가 있습니다. 두 가지 주요 문제는 API (대부분 C 지향적이며 인터페이스 비용이 많이들 수 있음)와 GC (대개 원시 처리량이 아닌 대기 시간 문제)입니다.
루안

1
@gbjbaanb CPU가 더 빠를뿐만 아니라 C ++과 C는 컴파일러와 런타임을 완벽하게하기 위해 수십 년이 걸렸으며 Java는 기본적으로 0에서 시작했습니다 (주로 멀티 플랫폼 플랫폼으로 설계됨). VM이 개선됨에 따라 (예 : 인터프리터에서 JIT 컴파일러로의 전환, GC 개선 등) Java 애플리케이션의 성능도 향상되었습니다. 여전히 C / C ++의 많은 장점은 "불필요한"것으로 간주되는 많은 점검을 피하면서 "아무것도 깨지 말자"접근 방식에 있습니다. 그러나 여전히 거대한 메모리 호그입니다. 실제로 CPU 사용량이 향상되면 종종 메모리 성능이 저하됩니다.)
Luaan

13

"포인터가 있기 때문에"C가 안전하지 않다고 주장하는 것은 재미있다. 반대의 경우도 마찬가지입니다. Java와 C #에는 실질적으로 포인터 만 있습니다 (기본이 아닌 유형의 경우). Java에서 가장 일반적인 오류는 아마도 Null Pointer Exception 일 것입니다 (참조 : https://www.infoq.com/presentations/Null-References-The-Billion-Dollar-Mistake-Tony-Hoare ). 두 번째로 가장 일반적인 오류는 아마도 사용되지 않는 객체 (예 : 닫힌 대화는 폐기되지 않음)에 대한 숨겨진 참조를 보유하고 있기 때문에 해제 할 수 없기 때문에 메모리 용량이 계속 증가하는 프로그램이 오래 실행되는 것입니다.

C #과 Java를보다 안전하고 안전하게 만드는 두 가지 기본 메커니즘이 있습니다.

  • 가비지 콜렉션은 프로그램이 버려진 오브젝트에 액세스하려고 시도 할 가능성을 줄입니다. 이로 인해 프로그램이 예기치 않게 종료 될 가능성이 줄어 듭니다. C와 달리 Java 및 C #은 기본적으로 비원시 데이터를 동적으로 할당합니다. 이로 인해 프로그램 논리가 실제로 더 복잡해 지지만 내장 가비지 수집은 비용이 많이 들지만 어려운 부분을 대신합니다.

최근의 C ++의 스마트 포인터는 프로그래머가 작업을 더 쉽게 해줍니다.

  • Java 및 C #은 정교한 런타임으로 해석 / 실행되는 중간 코드로 컴파일됩니다. 런타임은 프로그램의 불법 활동을 감지 할 수 있으므로 보안 수준이 향상됩니다. 프로그램이 안전하지 않게 코딩 된 경우에도 (두 언어 모두 가능) 이론상 각각의 런타임은 시스템에 "분리"되는 것을 방지합니다.
    런타임은 시도 된 버퍼 오버런으로부터 보호하지 않지만 이론 상으로는 그러한 프로그램의 악용을 허용하지 않습니다. 대조적으로 C 및 C ++에서는 프로그래머가 악용을 방지하기 위해 안전하게 코딩해야합니다. 이것은 보통 즉시 달성되지 않지만 검토와 반복이 필요합니다.

정교한 런타임도 보안 위험이라는 점은 주목할 가치가 있습니다. 새로 발견 된 안전 문제로 인해 2 주마다 Oracle이 JVM을 업데이트하고있는 것으로 보입니다. 물론 그것은 단일 프로그램보다 JVM을 확인하는 것이 훨씬 어렵 습니다.

따라서 정교한 런타임의 안전성은 모호하고 기만적입니다. 평범한 C 프로그램은 검토와 반복을 통해 합리적으로 안전하게 만들 수 있습니다. 일반적인 Java 프로그램은 JVM만큼 안전합니다. 즉, 실제로는 아닙니다. 못.

gets()링크에 관한 기사 는 핵심 언어가 아니라 오늘날 다르게 결정된 역사적 라이브러리 결정을 반영합니다.


3
원래 저자의 요점은 C에서 해당 포인터에 대해 확인되지 않은 조치를 취할 수 있다는 것입니다. Java에서는 즉시 예외가 발생합니다. C에서는 애플리케이션 상태가 손상 될 때까지 유효하지 않은 위치를 읽고 있다는 것을 인식하지 못할 수 있습니다.
Sam Dufel 2016 년

1
또한 stackoverflow.com/questions/57483/…-java에 "실제로 만 참조"가 있다고 말하는 것이 더 정확합니다.
Sam Dufel 2016 년

4
나는 명백한 포인터를 피하려는 시도로 모든 종류의 흥미로운 버그가 발생하는 것을 보았습니다. 일반적으로 근본적인 문제는 복사와 참조의 혼동입니다. C에서 무언가를 가리키는 포인터를 전달하면 수정하면 원본에 영향을 줄 것입니다. 포인터를 피하려는 일부 시도는 이러한 차이점을 모호하게하여 깊은 사본, 얕은 사본 및 일반적인 혼란의 미로로 이어집니다.
Arlie Stephens 2016 년

오라클의 JVM이 (악용 가능한 보안 취약점을 잃어 버리는 관점에서) 짜증이 나기 때문에 일반적으로 관리되는 언어의 런타임은 관리되는 언어를 사용하지 않는 것보다 더 많은 보안 문제를 유발합니다. 어도비 플래시는 웹 사이트에서의 비디오 및 애니메이션 재생은 본질적으로 엄청나게 안전하지 않아야합니다. 모든 Java 런타임이 Oracle / Sun의 1990 년대 빈티지 JVM abomination만큼 나쁘지는 않으며 모든 관리 언어가 Java 인 것은 아닙니다. (음, 분명히.)
주로

@halfinformed 잘; 나는 프로그램이 런타임만큼 안전하다고 말하면서 바이트 코드 인터프리터와 같은 큰 런타임보다 "평균"(읽기 : 작은) 프로그램을 안전하게 사용할 수 있다고 말했습니다. 그 진술은 부인할 수없는 것 같습니다. 특정 독립형 프로그램 또는 특정 런타임이 다른 것보다 다소 안전한지 여부는 각각의 복잡성과 디자인, 코딩 및 유지 관리 품질에 달려 있습니다. 예를 들어 sendmail이 Oracle의 Java VM보다 안전하다고는 말할 수 없습니다. 그러나 큐메일 일 수도 있습니다.
피터 A. 슈나이더

10

"안전"은 속도가 빠르기 때문에 "안전한"언어는 더 느린 속도로 수행됩니다.

C 또는 C ++와 같은 "위험한"언어를 사용하는 이유를 묻고 누군가에게 Python 또는 Java 등의 비디오 드라이버 등을 작성하고 "안전"에 대해 어떻게 느끼는지 확인하십시오. :)

진지하게, 픽셀, 레지스터 등을 조작 할 수 있으려면 머신의 코어 메모리에 가까워 야합니다. Java 또는 Python은 모든 유형의 성능에 적합한 속도로는 이것을 수행 할 수 없습니다 ... C 및 C ++ 포인터 등을 통해이 작업을 수행 할 수 있습니다 ...


20
일반적으로 안전 비용이 빠르다 는 것은 사실이 아닙니다 . 가장 안전한 언어는 컴파일 타임에 대부분의 검사를 수행합니다. O'Caml, Ada, Haskell, Rust는 평균 런타임 속도면에서 C보다 훨씬 뒤지지 않습니다. 그들이 않습니다 일반적으로 발생하는 것은 프로그램의 크기, 메모리 효율, 대기 시간에 상당한 오버 헤드, 그리고 분명히 시간을 컴파일합니다. 그리고, 그들은 금속에 가까운 물건에 어려움이 있습니다. 그러나 그것은 실제로 속도 문제가 아닙니다.
leftaroundabout

6
또한 C는 당신이 생각하는 것을하지 않습니다. C 는 추상 기계입니다 . 그것은 당신에게 어떤 것에 직접 액세스 할 수는 없습니다-좋은 일입니다. C가 개발 될 때 현대 어셈블리 (예 : TASM)는 고급 언어로 간주되었을 것입니다. 누군가가 "안전한"언어로 드라이버를 작성했다면 매우 기쁠 것입니다. 감사합니다. 보안 문제는 말할 것도없고 BSOD와 동결을 피하는 데 큰 도움이 될 것입니다. C.
Luaan

3
@Wintermute 당신은 정말로 안전 기능이 반드시 속도를내는 방법에 대한 의견을 말하기 전에 Rust를 찾아보고 싶을 것입니다. 지옥, C의 낮은 수준의 형식 시스템은 실제로 억제 (특히 거의 더 큰 C 프로젝트는 엄격한 앨리어싱 위반하지 않도록 방지하기 위해 관리 없음을 고려할 때 컴파일러 다르게 할 수있는 많은 유용한 최적화를 어딘가에 ).
Voo

7
@Wintermute 그래, 당신이 성능 오버 헤드를 도입하지 않고있는 안전 ++ C / C를 할 수없는 신화 내가 걸릴 이유입니다 매우 지속적이 (가 오히려 심각한 몇몇 이 확실히 사실 [확인 경계]입니다 영역). 이제 왜 녹이 더 널리 퍼지지 않습니까? 역사와 복잡성. Rust는 여전히 비교적 새롭고 Rust가 발명되기 전에 C로 작성된 가장 큰 시스템 중 많은 것이 존재했습니다. 훨씬 더 안전하더라도 새로운 언어로 백만 개의 LOC를 다시 쓰지 않을 것입니다. 또한 모든 프로그래머와 개는 C, Rust를 알고 있습니까? 충분한 사람들을 찾는 행운을 빕니다.
Voo

3
@Voo Dogs doing C? ... 내가 너무 많은 나쁜 코드를 보았을 것입니다 ... j / k Rust에 대해 취한 점 (방금 다운로드하여 설치 했으므로 추가 할 다른 변환이있을 수 있습니다) BTW Rust가 제대로하도록 ... "D"에 대해 같은 기능을 추가 할 수 있습니다 :)
Wintermut3

9

위의 모든 것 외에도 C를 다른 언어의 공통 라이브러리로 사용하는 일반적인 사용 사례가 하나 있습니다.

기본적으로 거의 모든 언어에는 C에 대한 API 인터페이스가 있습니다.

간단한 예를 들어, Linux / IOS / Android / Windows 용 공통 애플리케이션을 작성하십시오. 거기에있는 모든 도구 외에도 C에서 핵심 라이브러리를 수행 한 다음 각 환경에 대한 GUI를 변경했습니다.

  • iOS : ObjectiveC는 C 라이브러리를 기본적으로 사용할 수 있습니다
  • 안드로이드 : 자바 + JNI
  • Linux / Windows / MacOS : GTK / .Net에서는 기본 라이브러리를 사용할 수 있습니다. Python, Perl, Ruby를 사용하는 경우 각각 고유 한 API 인터페이스가 있습니다. (JNI로 다시 Java).

내 두 센트


필자가 PHP를 사용하는 것을 좋아하는 이유 중 하나는 거의 모든 라이브러리가 실제로 C로 작성 되었기 때문입니다. 고맙게도 PHP가 느리게 진행될 수 있기 때문입니다. '위험한'일을하고 (그래서 내가 다른 것보다 훨씬 더 많은 PHP 코드를 쓰는 경향이 있습니다-나는 거친 코드를 좋아 합니다! : D), 많은 함수 호출 아래에는 좋은 ol '가 있다는 것을 아는 것이 좋습니다. 성능 향상을위한 C 라이브러리 ;-) 대조적으로, C로 조잡한 코드를 작성하는 것은 큰 문제가되지 않습니다.
Gwyneth Llewelyn

7

C의 근본적인 어려움은 이름이 구문은 동일하지만 의미가 매우 다른 여러 방언을 설명하는 데 사용된다는 것입니다. 일부 방언은 다른 방언보다 훨씬 안전합니다.

Dennis Ritchie가 처음 디자인 한 C에서 C 문은 일반적으로 예측 가능한 방식으로 기계 명령어에 매핑됩니다. C는 부호있는 산술 오버플로와 같은 일이 발생했을 때 다르게 동작하는 프로세서에서 실행될 수 있기 때문에 산술 오버플로의 경우 기계가 어떻게 작동하는지 알지 못하는 프로그래머는 해당 컴퓨터에서 실행되는 C 코드가 어떤 동작을하는지 알지 못하지만 머신이 특정 방식으로 작동하는 것으로 알려진 경우 (예 : 자동 2의 보완 랩 어라운드) 해당 머신의 구현도 일반적으로 동일합니다. C가 빠르다고 평판을 얻은 이유 중 하나는 프로그래머가 에지 시나리오에서 플랫폼의 자연스러운 동작이 자신의 요구에 적합하다는 것을 알고있는 경우 프로그래머 나 컴파일러가 이러한 시나리오를 생성하기 위해 코드를 작성할 필요가 없기 때문입니다. .

불행히도, 컴파일러 작성자는 표준이 그러한 경우 구현이 수행해야하는 작업 (예측할 수없는 하드웨어 구현을 허용하기위한 여유도)에 대한 요구 사항을 부과하지 않기 때문에 컴파일러는 법률을 무효화하는 코드를 자유롭게 생성해야한다고 생각했습니다 시간과 인과성.

다음과 같은 것을 고려하십시오.

int hey(int x)
{
   printf("%d", x);
   return x*10000;
}
void wow(int x)
{
  if (x < 1000000)
    printf("QUACK!");
  hey(x);    
}

하이퍼 모던 (하지만 유행) 컴파일러 이론은 컴파일러가 "QUACK!"을 출력해야한다고 제안합니다. 조건이 거짓 인 경우에 프로그램은 결과적으로 무시 될 곱셈을 수행하는 정의되지 않은 동작을 호출하게됩니다. 표준은 컴파일러가 이러한 경우에 원하는 것을 수행 할 수 있도록하기 때문에 컴파일러가 "QUACK!"를 출력 할 수 있도록합니다.

C는 어셈블리 언어보다 안전했지만 하이퍼 현대 컴파일러를 사용할 때는 그 반대가 사실입니다. 어셈블리 언어에서 정수 오버플로는 계산으로 인해 의미없는 결과를 얻을 수 있지만 대부분의 플랫폼에서 그 영향의 범위에 해당합니다. 어쨌든 결과가 무시되면 오버플로는 중요하지 않습니다. 그러나 하이퍼 모던 C에서는 일반적으로 정의되지 않은 동작의 "양성"형태 (무시 된 계산에서 정수 오버플로)가 발생하더라도 임의의 프로그램이 실행될 수 있습니다.


1
하이퍼 현대 컴파일러에서도 C는 배열을 검사하지 않습니다. 그렇게하면 언어 정의와 호환되지 않습니다. 때로는 그 사실을 사용하여 배열의 중간에 추가 포인터가있는 배열을 만들어 음의 인덱스를 갖습니다.
robert bristow-johnson 2012

1
"QUACK!"을 생성하는 예제의 증거를보고 싶습니다. 무조건. x는 확실히 비교 시점에서 1000000보다 클 있으며 나중에 오버플로를 초래하는 평가는이를 방지하지 않습니다. 또한 오버 라이닝을 제거 할 수있는 인라인을 활성화 한 경우 암시 적 범위 제한에 대한 인수는 유지되지 않습니다.
Graham

2
@ robertbristow-johnson : 실제로, 표준은 예를 들어 int arr[5][[5]접근 시도가 arr[0][5]정의되지 않은 행동을 낳을 것이라고 명시 적으로 말합니다 . 이러한 규칙은 의 값에 관계없이 4 와 같은 arr[1][0]=3; arr[0][i]=6; arr[1][0]++;것으로 추론 되는 컴파일러를 가능하게합니다 . arr[1][0]i
supercat

2
@ robertbristow-johnson : 컴파일러가 갭없이 순차적으로 구조체 내에서 배열을 할당하더라도 배열 중 하나를 인덱싱해도 다른 배열에 영향을 줄 수 있다고 보장하지는 않습니다. gcc가 이러한 코드를 처리하는 방법에 대한 예는 godbolt.org/g/Avt3KW 를 참조하십시오 .
supercat

1
@ robertbristow-johnson : 나는 의회가 그 일을 설명하기 위해 논평했다. 컴파일러는 코드가 1을 s-> arr2 [0]에 저장 한 다음 s-> arr2 [0]을 증가시키는 것을 확인하므로 gcc는 중간에 쓰기 가능성을 고려하지 않고 코드가 단순히 값 2를 저장하도록하여 두 작업을 결합합니다. s-> arr1 [i]의 값은 s-> arr1 [0]의 값에 영향을 줄 수 있습니다 (표준에 따라 불가능하므로).
supercat

5

역사적 이유. 나는 종종 새로운 코드를 작성하지 않으며, 주로 수십 년 동안 실행되어 온 오래된 것들을 유지하고 확장합니다. 나는 그것이 Fortran이 아니라 C라는 것이 기쁘다.

어떤 학생이 "지구상에서 Y를 할 수있을 때 왜이 끔찍한 X를합니까?"라고 말하면서 자극을받을 수 있습니다. 글쎄, X는 내가 가진 일이며 청구서를 아주 잘 지불합니다. 나는 가끔 Y를 해왔고 재미 있었지만 X는 우리 대부분의 일입니다.


5

"위험한"이란 무엇입니까?

C가 "위험하다"는 주장은 언어 화염 전쟁에서 자주 이야기하는 지점입니다 (대부분 Java와 비교할 때). 그러나이 주장에 대한 증거는 불분명하다.

C는 특정 기능 세트가있는 언어입니다. 이러한 기능 중 일부는 다른 유형의 언어에서 허용되지 않는 특정 유형의 오류를 허용 할 수 있습니다 (C의 메모리 관리 위험은 일반적으로 강조 표시됨). 그러나이없는 C가 다른 언어보다 더 위험 인수와 동일한 전체 . 나는이 시점에서 설득력있는 증거를 제공하는 사람을 모른다.

또한 "위험한"은 상황에 따라 다릅니다. 무엇을하려고하는지, 어떤 종류의 위험이 걱정됩니까?

많은 맥락에서 C를 고급 언어보다 "위험한"것으로 생각합니다. 기본 기능을보다 수동으로 구현해야하므로 버그의 위험이 증가하기 때문입니다. 예를 들어, 다른 언어는이 기능을 훨씬 쉽게 수행 할 수있는 기능이 있기 때문에 기본 텍스트 처리 또는 C에서 웹 사이트 개발은 일반적으로 어리 석습니다.

그러나 C와 C ++는 미션 크리티컬 한 시스템에 널리 사용됩니다. 더 엄격한 언어를 직접 제어 할 수있는 작은 언어는 그 맥락에서 "safer"로 간주되기 때문입니다. 에서 아주 좋은 스택 오버플로 대답 :

C 및 C ++는 이러한 유형의 응용 프로그램을 위해 특별히 설계되지 않았지만 몇 가지 이유로 임베디드 및 안전에 중요한 소프트웨어에 널리 사용됩니다. 메모의 주요 속성은 메모리 관리 (예를 들어 가비지 수집을 피할 수 있도록 함), 간단하고 잘 디버깅 된 핵심 런타임 라이브러리 및 성숙한 도구 지원입니다. 오늘날 사용되는 많은 임베디드 개발 툴 체인은 현재 기술이었던 당시 1980 년대와 1990 년대에 처음 개발되었으며 당시 유닉스 문화에서 왔기 때문에 이러한 툴은 이런 종류의 작업에 인기를 유지합니다.

오류를 피하기 위해 수동 메모리 관리 코드를주의 깊게 검사해야하지만 가비지 수집에 의존하는 언어로는 사용할 수없는 응용 프로그램 응답 시간을 어느 정도 제어 할 수 있습니다. C 및 C ++ 언어의 핵심 런타임 라이브러리는 비교적 단순하고 성숙하며 잘 이해되어 있으므로 가장 안정적인 플랫폼 중 하나입니다.


2
하이퍼 모던 C는 어셈블리 언어 나 C의 저수준 방언보다 위험하기 때문에 자연 머신 코드 작업이 수행되는 엣지 케이스에 관계없이 C 작업을 머신 코드 작업으로 일관되게 변환하는 것처럼 일관되게 동작합니다. 동작을 정의했지만 C 표준은 요구 사항을 부과하지 않습니다. 정수 오버플로가 시간 규칙을 무효화 할 수있는 초현대적 접근 방식과 인과 관계는 안전한 코드 생성에 훨씬 덜 적합합니다.
supercat

5

기존 답변에 추가하기 위해서는 상대적 안전으로 인해 프로젝트에 Python 또는 PHP를 선택한다고 말하는 것이 좋습니다. 그러나 누군가는 그 언어를 구현해야하며, 그렇게 할 때 아마도 C에서 언어를 수행 할 것입니다.

- 사람들이 C를 사용하는 이유 그래서 그건 덜 위험한 도구를 만들기 위해 당신이 사용하고자합니다.


2

귀하의 질문을 다시 말씀 드리겠습니다.

학습을 고려하고 있습니다 [도구].

그러나 [위험하게] 사용될 수 있다면 사람들이 왜 [도구] (또는 [관련 도구])를 사용합니까?

프로그래밍 언어를 포함하여 모든 흥미로운 도구를 위험하게 사용할 수 있습니다. 당신은 배울 당신이 할 수 있도록 더 (당신이 도구를 사용할 때 덜 위험이 만들어 졌는지 등) 더. 특히, 도구가 유용한 기능을 수행 할 수 있도록 도구를 배웁니다 (해당 도구가 사용자가 알고있는 도구 중 최고의 도구 인 경우를 인식 할 수 있음).

예를 들어, 나무 블록에 직경 6mm, 깊이 5cm의 원통형 구멍을 넣어야하는 경우 드릴은 LALR 파서보다 훨씬 나은 도구입니다. 이 두 도구가 무엇인지 아는 경우 올바른 도구가 무엇인지 알고 있습니다. 드릴, 짜잔!, 구멍을 사용하는 방법을 이미 알고 있다면.

C는 또 다른 도구입니다. 일부 작업은 다른 작업보다 낫습니다. 여기에 다른 답변이 있습니다. C를 배우면 그것이 올바른 도구 일 때와 그렇지 않을 때를 알게 될 것입니다.


이 답변은 질문이 "주요 의견 기반"으로 던져지는 이유입니다. C가 장점을 가지고 있다고 말하지 말고 그들이 무엇인지 말하십시오!
reinierpost

1

나는 C 학습을 고려하고 있습니다

C를 배우지 않을 특별한 이유는 없지만 C ++을 제안합니다. 그것은 많은 양의 "extras"를 가지고 C가하는 많은 것을 제공한다 (C ++는 C의 슈퍼 세트이기 때문에). C ++보다 먼저 C를 배우는 것은 불필요합니다. 효과적으로 분리 된 언어입니다.

다른 방법으로 C가 목공 도구 세트라면 다음과 같습니다.

  • 망치
  • 손톱
  • 손보고
  • 핸드 드릴
  • 블록 샌더
  • 끌 (아마도)

이러한 도구를 사용하여 무엇이든 만들 수 있지만 좋은 작업 에는 많은 시간과 기술이 필요합니다.

C ++은 지역 철물점에있는 전동 공구 모음입니다.

기본 언어 기능을 사용하여 시작하면 C ++에는 추가 학습 곡선이 거의 없습니다.

그러나 사람들이 왜 '위험하게'사용될 수 있다면 C (또는 C ++)를 사용합니까?

어떤 사람들은 IKEA의 가구를 원하지 않기 때문입니다. =)

그러나 C 또는 C ++보다 "높은"언어가 많은 경우 특정 측면에서 사용하기 쉽게 "잠재적 인"언어를 사용할 수 있지만 이것이 항상 좋은 것은 아닙니다. 무언가가 행해지는 방식이 마음에 들지 않거나 기능이 제공되지 않으면 할 수있는 일이 많지 않을 것입니다. 반면에 C와 C ++는 많은 것들을 상당히 직접적으로 접근하거나 (하드웨어 나 OS 측면에서) 직접 빌드 할 수있는 충분한 "저수준"언어 기능 (포인터 포함)을 제공합니다. 구현 된 언어

보다 구체적으로, C는 많은 프로그래머에게 바람직한 다음과 같은 기능 세트를 가지고 있습니다.

  • 속도 -수년에 걸쳐 상대적 단순성 및 컴파일러 최적화로 인해 기본적으로 매우 빠릅니다. 또한 많은 사람들이 언어를 사용할 때 특정 목표에 대한 많은 지름길을 알아 냈으므로 잠재적으로 더 빠릅니다.
  • 크기 -속도에 대해 나열된 것과 유사한 이유로 C 프로그램을 매우 작게 만들 수 있으며 (실행 파일 크기 및 메모리 사용 측면에서) 메모리가 제한된 환경 (예 : 임베디드 또는 모바일)에 적합합니다.
  • 적합성 -C는 오랫동안 사용되어 왔으며 모든 사람들이 사용할 수있는 도구와 라이브러리가 있습니다. 언어 자체도 까다 롭지 않습니다. 프로세서가 명령과 메모리를 실행하여 내용을 담을 것으로 예상합니다.

    또한 ABI (Application Binary Interface) 라고하는 것이 있습니다 . 즉, 프로그램이 머신 코드 레벨에서 통신하는 방법이므로 API (Application Programming Interface) 보다 이점이 있습니다 . C ++과 같은 다른 언어에는 ABI가있을 수 있지만 일반적으로 C보다 덜 균일 (합의)되므로 C는 ABI를 사용하여 어떤 이유로 다른 프로그램과 통신하려는 경우 훌륭한 기초 언어를 만듭니다.

프로그래머가 Java 나 Python 또는 Visual Basic과 같은 다른 컴파일 된 언어를 사용하지 않는 이유는 무엇입니까?

효율성 (때로는 메모리에 비교적 직접 액세스하지 않고는 구현할 수없는 메모리 관리 체계)

포인터를 사용하여 메모리에 직접 액세스하면 메모리 큐비 홀의 작은 것과 0에 멍청한 발을 직접 넣을 수 있고 그 교사가 장난감을 나눠 줄 때까지 기다릴 필요가 없을 때 깔끔한 (보통 빠른) 트릭이 많이 생깁니다. 플레이 타임에 다시 퍼팅하십시오.

요컨대, 물건을 추가하면 잠재적으로 지연이 발생하거나 원치 않는 복잡성이 생길 수 있습니다.

스크립트 언어 및 그와 관련하여 C (또는 컴파일 된 언어)가 기본적으로 수행하는 것처럼 보조 프로그램이 필요한 언어를 효율적으로 실행하려면 열심히 노력해야합니다. 온더 플라이 인터프리터를 추가하면 본질적으로 믹스에 다른 프로그램을 추가하기 때문에 실행 속도가 감소하고 메모리 사용량이 증가 할 수 있습니다. 프로그램 효율성은이 보조 프로그램의 효율성에 따라 원래 프로그램 코드를 얼마나 잘 작성했는지 (나쁘게 =) 의존합니다. 말할 것도없이 프로그램은 종종 두 번째 프로그램에 전적으로 의존하여 실행되기도합니다. 두 번째 프로그램이 특정 시스템에 어떤 이유로 존재하지 않습니까? 코드가 없습니다.

사실, 도입 아무것도 가능성이 느려지거나 코드를 복잡하게 "추가"를. "두려운 포인터가없는"언어의 경우, 프로그램이 여전히 동일한 메모리 액세스 작업을 수행 하기 때문에 다른 코드 비트가 사용자를 정리하거나 "안전한"방법을 찾기 위해 항상 기다리고 있습니다. 포인터. 당신은 그것을 처리하는 사람이 아닙니다 (그래서 f * ck 할 수는 없습니다, genius = P).

위험하다는 것은 포인터와 다른 유사한 것들을 의미합니다. [...] Stack Overflow 질문처럼 gets 함수가 왜 그렇게 사용되어서는 안 되는가?

허용 된 답변에 따라 :

"이 언어는 1999 년 ISO C 표준까지 언어의 공식적인 부분으로 유지되었지만 2011 년 표준에 의해 공식적으로 제거되었습니다. 대부분의 C 구현은 여전히이를 지원하지만 최소한 gcc는이를 사용하는 모든 코드에 대해 경고를 표시합니다."

뭔가 언어에서 수행 할 수 있기 때문에, 그것은 그 개념 있어야 할 수는 바보입니다. 언어에는 결함이 있습니다. 이전 코드와의 호환성을 위해이 구문을 계속 사용할 수 있습니다. 그러나 프로그래머가 gets ()를 사용하도록 강요하는 것은 없으며 실제로이 명령은 본질적으로 더 안전한 대안으로 대체되었습니다.

요컨대 gets () 문제는 포인터 문제가 아닙니다. . 메모리를 안전하게 사용하는 방법을 반드시 알 필요는없는 명령에 문제가 있습니다. 추상적 의미에서, 이것은 모든 포인터 문제입니다-원하지 않는 것을 읽고 쓰는 것. 포인터에 대해서는 문제가되지 않습니다. 포인터 구현에 문제가 있습니다.

명확히하기 위해, 의도하지 않은 메모리 위치에 실수로 액세스 할 때까지 포인터는 위험하지 않습니다. 그렇다고해서 컴퓨터가 녹거나 폭발하는 것은 아닙니다. 대부분의 경우 프로그램이 제대로 작동하지 않습니다.

포인터가 메모리 위치에 대한 액세스를 제공하고 데이터와 실행 코드가 함께 메모리에 존재하기 때문에 메모리를 올바르게 관리하려는 실수로 인한 손상의 위험이 충분히 있습니다.

실제로 직접 메모리 액세스 작업은 몇 년 전에 비해 일반적으로 적은 이점을 제공하기 때문에 C ++와 같이 가비지 수집되지 않은 언어 조차도 스마트 포인터 와 같은 기능을 도입 하여 메모리 효율성과 안전성 사이의 격차를 해소 할 수 있습니다.

요약하면, 포인터를 안전하게 사용하는 한 포인터를 두려워 할 이유가 거의 없습니다. 사우스 파크의 Steve "The Crocodile Hunter"Irwin 버전에서 힌트를 얻으십시오 . 엄지 손가락을 악어의 벙어리에 집어 넣지 마십시오 .


2
C 대신 C ++을 배우라는 제안에 동의하지 않습니다. 좋은 C ++를 작성하는 것은 좋은 C를 작성하는 것보다 어렵고 C ++를 읽는 것이 C를 읽는 것보다 훨씬 어렵습니다. 따라서 C ++의 학습 곡선은 훨씬 가파 릅니다. "C ++는 C의 슈퍼 세트입니다"이것은 부츠가 슬리퍼의 슈퍼 세트라고 말하는 것과 거의 비슷합니다. 각기 다른 장점과 사용법이 있으며 각각 다른 기능과는 다른 기능이 있습니다.
martinkunev 2016 년

"좋은 C ++를 작성하는 것은 좋은 C를 작성하는 것보다 어렵습니다."-물론입니다. =) "[C]를 읽는 것이 C를 읽는 것보다 훨씬 어렵습니다."-고급 프로그래밍은 마술과 구별 할 수 없을 것 같습니다. 이 카테고리에서. "따라서 C ++의 학습 곡선은 훨씬 가파 릅니다." -장기적으로는 그렇습니다. 단기적으로는 그렇지 않습니다 (내 의견). 일화 적으로 C 및 C ++의 대부분의 기본 언어 과정은 C ++ 클래스를 제외하고는 거의 동일한 일반 유형의 자료를 다룰 수 있습니다.
Anaksunaman

2
"각각 다른 장점과 사용법이 있으며 각각 다른 기능과는 다른 기능이 있습니다." -언급했듯이 "C [.]를 배우지 않을 특별한 이유는 없습니다."C는 훌륭한 언어이며 저는이를 고수합니다. OP 또는 다른 사람에게 적합하면 학습을 전적으로 지원합니다. =)
Anaksunaman 2016 년

C 학습은 기계가 어떻게 작동하는지 알려줍니다 (완전히 내려 가지는 않지만 여전히 금속에 한 걸음 더 다가갑니다). 그것이 그것을 배우는 아주 좋은 이유입니다.
Agent_L

1

항상 그렇듯이 프로그래밍 언어는 문제 해결의 결과 일뿐입니다. 실제로 C뿐만 아니라 문제를 해결할 때 사용할 수있는 적절한 도구 상자가 있어야하는 많은 다른 언어 (및 컴퓨터를 프로그래밍하는 다른 방법, GUI 도구 또는 명령 해석기)를 배워야합니다.

때로는 Java 기본 라이브러리에 포함 된 문제에 문제가있는 경우가 있습니다. 이러한 경우 Java를 사용하여 Java를 선택할 수 있습니다. 다른 경우에는 .NET 런타임에서 훨씬 간단한 Windows에서 무언가를 수행해야 할 수도 있으므로 C # 또는 VB를 사용할 수 있습니다. 문제를 해결하는 그래픽 도구 나 명령 스크립트가있을 수 있습니다. 여러 플랫폼에서 GUI 응용 프로그램을 작성해야 할 수도 있습니다. JDK에 포함 된 라이브러리를 고려할 때 Java가 옵션 일 수 있지만, 다시 한 대상 플랫폼에 JRE가 없을 수 있으므로 대신 C 및 SDL (또는 유사)을 선택할 수 있습니다.

C는이 도구 세트에서 일반적이고 작으며 빠르며 머신 코드로 컴파일되기 때문에 중요한 위치에 있습니다. 또한 태양 아래 모든 플랫폼에서 지원됩니다 (다시 컴파일하지 않아도 됨).

결론은 가능한 많은 도구, 언어 및 패러다임을 배워야한다는 것입니다.

"나는 X 프로그래머입니다"(X = C, C ++, Java 등)라는 사고 방식에서 벗어나십시오.

"나는 프로그래머입니다"를 사용하십시오.

프로그래머는 머신에 워크로드를 수행하도록 지시하여 문제점을 해결하고 알고리즘을 설계합니다. 이야기의 끝. 이것은 언어와 관련이 없습니다. 가장 중요한 기술은 문제 해결 및 구조적 문제의 논리적 분석, 언어 기술 / 선택은 항상 보조적이며 문제의 본질에 따른 결과입니다.

C에 관심이 있다면 흥미로운 길은 Go로 스킬 셋을 확장하는 것입니다. Go는 가비지 수집 및 인터페이스뿐만 아니라 내장 된 스레딩 모델 / 채널을 통해 개선 된 C로, C의 많은 이점 (예 : 포인터 산술 및 머신 코드 컴파일)을 제공합니다.


0

그것은 당신이 그것으로 무엇을하려고하는지에 달려 있습니다. C는 어셈블리 언어를 대체하도록 설계되었으며 기계 언어에 가장 가까운 고급 언어입니다. 따라서 크기와 성능면에서 오버 헤드가 적으며 시스템 프로그래밍 및 작은 설치 공간이 필요하고 기본 하드웨어에 가까워지는 기타 작업에 적합합니다.


0

가장 효율적인 할당 자와 데이터 구조를 효과적으로 구현하는 데 종종 필요한 것처럼 데이터의 비트 및 바이트 수준, 메모리의 원시 동종 데이터 수집으로 작업 할 때는 안전이 없습니다. 안전성은 주로 강력한 데이터 유형 관련 개념이며 메모리 할당자는 데이터 유형에서 작동하지 않습니다. 비트 및 바이트와 함께 작동하여 잠재적으로 한 데이터 유형을 나타내는 순간과 다른 비트를 동일한 비트 및 바이트와 풀링합니다.

이 경우 C ++을 사용하더라도 중요하지 않습니다. 포인터 static_casts에서 캐스트 void*하고 비트와 바이트로 작업 하기 위해 코드 전체에 계속 뿌려 지고 C보다 형식 시스템을 존중하는 것과 관련된 더 많은 번거 로움을 처리하는 C보다 훨씬 간단한 유형 시스템이 있습니다. 에 memcpy비트 타입 시스템을 통해 불도에 대한 걱정없이 주위 바이트.

실제로 C ++보다 더 위험한 코드를 작성하지 않고 비트 및 바이트의 저수준 컨텍스트에서 전체적으로 더 안전한 언어 인 C ++에서 작업하기가 더 어렵습니다. vptr을 덮어 쓰고 적절한 시간에 복사 생성자와 소멸자를 호출하지 못했습니다. 이러한 유형을 존중하고 새롭고 수동으로 호출자 등을 배치하는 데 적절한 시간이 걸리면 RAII가 실용적이지 않고 예외를 달성하기에는 너무 낮은 수준의 컨텍스트에서 예외 처리의 세계에 노출됩니다. 이러한 저수준 컨텍스트에서의 안전은 매우 어렵습니다 (어떤 기능도 모든 가능성을 던지고 잡을 수 있고 마치 아무 일도 일어나지 않는 것처럼 불가분의 트랜잭션으로 부작용을 롤백하는 것처럼 가장해야합니다). C 코드는 종종 "

그리고 여기서 "위험한"언어를 사용할 수없는 언어로 이러한 할당자를 구현하는 것은 불가능합니다. 그들이 제공하는 할당 자 (C 또는 C ++에서 구현되었을 가능성이 가장 큰)에 의존하고 그것이 당신의 목적에 충분하기를 바랍니다. 거의 항상 더 효율적이지만 덜 일반적인 할당 자 및 데이터 구조는 특정 목적에 적합하지만 사용자의 목적에 맞게 특별히 조정되었으므로 훨씬 더 좁게 적용 할 수 있습니다.

대부분의 사람들은 원래 C 또는 C ++로 구현 된 코드를 호출하거나 이미 구현 된 어셈블리를 호출 할 수 있기 때문에 C 또는 C ++을 좋아하지 않아도됩니다. C에서 이미 구현 된 기존 이미지 처리 기능의 라이브러리를 사용하는 이미지 프로그램을 개별 픽셀을 통해 가장 낮은 수준의 루핑 수준으로 혁신하지 않는 이미지 프로그램을 함께 묶는 것과 같이 높은 수준의 혁신을 통해 많은 이점을 얻을 수 있습니다. 이전에는 볼 수 없었던 매우 친숙한 사용자 인터페이스 및 워크 플로우를 제공합니다. 이 경우 소프트웨어의 요점이 저수준 라이브러리로 높은 수준의 호출을하는 것이라면 ( "각 픽셀이 아닌이 전체 이미지를 처리하고 무언가를 수행하십시오" ), 아마도 조기 최적화 일 수 있습니다. C에서 그러한 응용 프로그램을 작성하려고 시도하기까지합니다.

그러나 이전에 전혀 보지 못했던 새로운 이미지 필터와 같이 낮은 수준의 방식으로 데이터에 액세스하는 데 도움이되는 낮은 수준에서 새로운 일을하고 있다면 HD 비디오를 실시간으로 작업하기에 충분히 빠릅니다. 조금 위험합니다.

당연히이 물건을 가져가는 것은 쉽습니다. 저수준의 언어가 쓸모없고, 확실히 괜찮은 게임이라는 의미로 파이썬으로 3D 비디오 게임을 만드는 것이 어떻게 가능한지 지적한 페이스 북 게시물을 기억합니다. 그러나 파이썬은 C에서 구현 된 라이브러리를 고수준 호출하여 모든 힘든 작업을 수행했습니다. 기존 라이브러리를 고수준 호출하여 Unreal Engine 4를 만들 수 없습니다. 언리얼 엔진 4도서관. 조명에서 노달 청사진 시스템에 이르기까지 다른 라이브러리 및 엔진에는 존재하지 않았던 모든 종류의 작업을 수행했으며 코드를 컴파일하고 실행하는 방법에 대해 설명했습니다. 낮은 엔진 / 코어 / 커널 수준에서 혁신을 원한다면 낮은 수준에 도달해야합니다. 모든 게임 개발자가 고급 안전 언어로 전환 한 경우 Unreal Engine 5 또는 6 또는 7은 없을 것입니다. 40 년이 지난 후에도 여전히 언리얼 엔진을 사용하는 사람들이있을 것입니다. 이전 엔진에 대한 높은 수준의 호출만으로 차세대 엔진을 사용할 수 있습니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.