나는 C가 프로그래밍의 원리를 배우기에 좋은 언어라고 생각합니다. 루비와 같은 고급 언어에서 "매직 된"저급 언어로 무엇을 배울 수 있습니까?
나는 C가 프로그래밍의 원리를 배우기에 좋은 언어라고 생각합니다. 루비와 같은 고급 언어에서 "매직 된"저급 언어로 무엇을 배울 수 있습니까?
답변:
컴퓨터 과학의 일반적인 추상 의미에서 C에는 존재하지만 고급 언어에는 존재하지 않는 원칙은 없습니다. 모든 컴퓨터 과학은 알고리즘으로 요약되며 모든 알고리즘은 C와 같이 Turing-complete 인 모든 언어로 구현 될 수 있습니다.
C가 더 높은 수준의 언어에서 나눠지는 차이점은 기계어 코드가 C와 차이가 나는 차이점과 비슷합니다. 기계와 코드의 관계.
고급 언어로 코드를 작성할 때 코드가 기계와 상호 작용하는 방식에 (일반적으로) 신경 쓰지 않아도됩니다. 언어가 자체적으로 정의한 가상 머신은 코드 실행의 여러 측면을 숨 깁니다.
C에서는 프로그램과 메모리의 상호 작용이 최전선에서 유지됩니다. 단순히 힙 사용을 관리해야하는 것 이상이며, 코드와 스택의 상호 작용, 코드의 단순한 메모리 액세스 가 코드의 동작 및 성능에 미치는 영향, 메모리 액세스 순서조차 포함하지 않습니다. 잘못된 시간에 잘못된 메모리를 읽으면 성능이 효과적으로 저하 될 수 있으므로주의를 피할 수 있습니다.
높은 수준의 언어에서 이러한 것들은 분명하지 않습니다. 메모리는 사용자 모르게, 때로는 프롬프트없이 할당 및 할당 해제됩니다. 대부분의 경우 이것은 단순히 통제 할 수없는 것입니다. 대부분의 메모리 할당시기, 장소, 방법 및 이유는 단순히 숨겨져 있습니다.
마찬가지로 기계 코드 또는 어셈블리 코드를 작성하면 포 그라운드에 더 많은 세부 정보가 표시됩니다. 거의 외부에 거의 아무것도 남지 않으며 코드는 모든 할당, 모든 리소스, 전달되는 모든 데이터를 인식해야합니다. CPU의 레지스터를 통해-고급 언어에서 제거 된 지식.
나는 C가 프로그래밍의 원리를 배우기에 좋은 언어라는 것을 알고 있습니다.
동의하지 않습니다. C에는 프로그래밍의 원리를 배우기에는 너무 많은 기능이 없습니다. 추상화를 생성하는 C의 기능은 끔찍하며 추상화는 프로그래밍의 핵심 원칙 중 하나입니다.
하드웨어의 작동 방식과 머신에 대한 기계적인 동정을 배우려면 명령어 세트 아키텍처라고하는 머신 코드를 배우고 최신 CPU의 캐시 구성을 연구해야합니다. 어셈블리 언어를 권장하지 않고 하드웨어 명령어 만 이해하면 컴파일러에서 생성하는 내용을 이해할 수 있습니다.
프로그래밍 원리를 배우려면 Java, C # 또는 Swift와 같은 현대 언어 또는 Rust와 같은 수십 가지 언어 중 하나를 사용하십시오. 또한 기능을 포함한 다양한 종류의 프로그래밍 패러다임을 연구하십시오.
대부분의 프로그래밍 언어는 추상 기계로 설명됩니다. 그런 다음 컴파일러, 링커, 어셈블러, 인터프리터, 정적 분석기, 중간 언어 및 하드웨어와 같은 도구 세트를 사용하여 구현됩니다.이 도구 는 프로그램에서 관찰 한 것처럼 최소한 추상 기계의 예상되는 모든 동작을 존중하는 결과를 종합적으로 생성합니다. .
C는 위 규칙의 예외가 아닙니다. 실제 하드웨어에 대한 개념이없는 추상 시스템으로 설명됩니다.
따라서 사람들이 C가 컴퓨터의 실제 작동 방식을 가르쳐 준다고 말할 때 일반적으로 C는 C의 작동 방식을 가르쳐줍니다. 그러나 C는 시스템 프로그래밍에 널리 퍼져 있기 때문에 많은 사람들이 컴퓨터 자체와 혼동하기 시작합니다. 저는 개인적으로 컴퓨터 자체의 작동 방식을 아는 것보다 C의 작동 방식을 아는 것이 더 중요하다고 말합니다.
그러나 여전히 C와 컴퓨터 는 다릅니다. 실제 하드웨어는 실제로 C 사양을 아동용 책처럼 읽게하는 방식으로 복잡합니다. 하드웨어 작동 방식에 관심이 있으시면 언제든지 설명서를 찾아 어셈블러에서 코드 작성을 시작할 수 있습니다. 또는 언제든지 디지털 회로에 대해 배우기 시작하여 직접 하드웨어를 설계 할 수 있습니다. (최소한, 당신은 높은 수준의 C가 얼마나 좋은지 알게 될 것입니다.)
실제로 하드웨어에 대해 배우는 것은 C 이외의 것을 포함하지만 C는 오늘날 프로그래머에게 다른 것을 가르 칠 수 있습니까?
나는 그것이 달려 있다고 생각합니다.
이러한 가능성 중 하나를 너무 빨리 선택하지 마십시오. 나는 몇 년 동안 코드를 작성해 왔지만 어느 것이 정답인지, 정답이 둘 중 하나인지, 또는이 문제에 대한 정답과 같은 것이 있는지 전혀 모른다.
나는 당신이 아마 두 가지 옵션을 모두 내가 설명한 순서대로 느슨하게 적용해야한다고 생각하는 경향이 있습니다. 그러나 이것이 실제로 기술적 인 문제라고 생각하지 않습니다. 나는 그것이 대부분 교육적인 것이라고 생각합니다. 모든 사람은 크게 다른 방식으로 배우는 것 같습니다.
적어도 내가 제안한 두 번째 옵션을 포함하여 위의 질문에 대답했다면, 당신은 이미 당신의 벨트 아래에 몇 가지 답변을 가지고 있습니다 : 더 높은 수준의 언어로 배울 수있는 것은 C 나에서 다시 발명함으로써 더 잘 배울 수 있습니다 믹스에 C를 첨가하여 최소 팽창.
그러나 대답에 관계없이 C (및 소수의 다른 언어)에서 거의 독점적으로 배울 수있는 몇 가지 사항이 있습니다.
C는 역사적으로 중요합니다. 그것은 우리가 어디에서 왔는지보고 감사 할 수 있고 우리가 어디로 가고 있는지에 대해 조금 더 많은 맥락을 얻을 수있는 이정표입니다. 특정 제한이 존재하는 이유를 이해할 수 있으며 특정 제한이 해제되었음을 알 수 있습니다.
C는 안전하지 않은 환경에서 작업하도록 가르 칠 수 있습니다. 즉, 어떤 이유로 든 언어 (어떤 언어)로도 할 수 없거나하지 않을 때 등을 보도록 훈련시킬 수 있습니다. 이렇게하면 버그가 거의 발생하지 않고 안전한 프로그램에서 약간의 속도를 내기 위해 (예 : 포인터 사용) 일시적으로 안전을 끌 수 있기 때문에 안전한 환경에서도 더 나은 프로그래머가 될 수 있습니다. 안전이 런타임 비용과 함께 제공되는 경우 C #에서).
C는 모든 객체에 스토리지 요구 사항, 메모리 레이아웃, 유한 주소 공간을 통해 메모리에 액세스 할 수 있다는 사실 등을 알려줄 수 있습니다. 다른 언어에서는 이러한 문제에주의를 기울일 필요가 없지만, 일부 직관을 통해보다 현명한 결정을 내리는 데 도움이되는 경우가 있습니다.
C는 빌드 시스템을 통해 링크 및 오브젝트 파일 및 기타 복잡한 세부 사항에 대해 알려줄 수 있습니다. 이를 통해 네이티브 컴파일 된 프로그램이 소스 코드에서 실행으로 이동하는 방식에 대한 유용한 실습을 제공 할 수 있습니다.
C는 정의되지 않은 행동의 개념을 통해 새로운 방식으로 생각하도록 마음을 구부릴 수 있습니다. 정의되지 않은 동작은 소프트웨어 개발에서 내가 가장 좋아하는 개념 중 하나입니다. 비 클래식 컴파일러에 미치는 영향에 대한 연구는 다른 언어에서 얻을 수없는 독특한 정신 운동이기 때문입니다. 그러나이 부분을 충분히 이해하기 전에 시행 착오를 거부하고 신중하고 신중하게 언어 공부를 시작해야합니다.
그러나 C가 작은 언어 인 사용자에게 부여 할 수있는 가장 중요한 실현은 모든 프로그래밍이 데이터와 운영으로 귀결 된다는 생각입니다 . 가상 디스패치가있는 계층 구조 및 인터페이스가있는 모듈 식 클래스 또는 순수한 수학 함수를 사용하여 조작되는 우아한 불변 값을보고 싶을 수 있습니다. 그리고 그것은 모두 괜찮습니다. 그러나 C는 그것이 단지 데이터 + 연산 이라는 것을 상기시켜 줄 것입니다 . 그것은 당신이 상당히 많은 정신 장벽을 무너 뜨릴 수 있기 때문에 유용한 사고 방식입니다.
C가 학습에 좋은 이유는 어떤 원리도 가르치지 않기 때문 입니다. 일이 어떻게 작동 하는지 가르쳐줍니다 .
C는 70 년대 또는 80 년대의 오래된 오래된 자동차 중 하나와 비교할 수 있습니다. 나사를 찢고 나사로 조이고 각 부품의 작동 방식과 손으로 볼 수있는 다른 부품과 함께 작동하는 방식을 이해할 수 있습니다. 모든 부품을 이해하면 전체 작동 방식을 매우 명확하게 파악할 수 있습니다.
현대 언어는 엔진이 기본적으로 블랙 박스 인 일반 자동차와 비슷하며 일반 자동차 소유자가 이해하기에는 너무 복잡합니다. 그 차는 많은 일을 할 수 있습니다. 요즘에는 스스로 운전하는 법을 배우고 있습니다. 이러한 복잡성과 편의성으로 인해 사용자 인터페이스는 실제로 엔진에서 진행되는 작업에서 훨씬 더 멀어졌습니다.
C에서 프로그래밍을 배우면 컴퓨터로 만들어진 많은 나사와 너트에 닿게됩니다. 이를 통해 기계 자체에 대한 이해를 높일 수 있습니다. 예를 들어, 다음과 같이 긴 문자열을 만드는 것이 좋지 않은 이유를 이해할 수 있습니다.
java.lang.String result = "";
for(int i = 0; i < components.size; i++) {
result = result + components[i];
};
(이것이 올바른 Java이고, 한동안 사용하지 않았기를 바랍니다 ...)이 코드 예제에서 루프가 2 차 복잡성을 갖는 이유는 분명하지 않습니다. 그러나 이것이 사실이며, 연결할 수백만 개의 작은 구성 요소가있을 때이 코드가 분쇄 중단되는 이유입니다. 숙련 된 C 프로그래머는 문제의 위치를 즉시 알고 있으며 이러한 코드 작성을 피할 수 있습니다.
for(int i = 0; i < strlen(s); i++)
C로 작성하면 루프는 2 차 복잡성을 갖게되며 Java 예제에서와 마찬가지로 명백하지 않습니다. ;-)
"프로그래밍 배후의 원리", 특히 이론적 원리를 배우는 데 C보다 더 나은 언어가 있지만 C는 공예품에 대해 실용적이고 중요한 것들을 배우는 것이 좋습니다. greyfade의 대답은 확실하지만 IMHO는 메모리를 직접 관리하는 방법보다 C에서 배울 수있는 것이 더 많습니다. 예를 들어
예외가없는 상태에서 완전한 오류 처리로 프로그램을 만드는 방법
객체 지향에 대한 언어 지원없이 프로그램에서 구조를 만드는 방법
동적 크기 목록, 사전 또는 유용한 문자열 추상화와 같은 데이터 구조가 없을 때 데이터를 처리하는 방법
컴파일러 또는 런타임 환경이 자동으로 경고하지 않는 경우에도 배열 오버플로와 같은 일반적인 오류를 피하는 방법
템플릿 또는 제네릭에 대한 언어 지원없이 제네릭 솔루션을 만드는 방법
물론 메모리를 직접 관리하는 방법을 배울 수 있다고 언급 했습니까? ;-)
또한 C를 배우면 C ++, Java, C #, Objective C의 구문 공통점이 어디에서 나오는지 알게됩니다.
2005 년 Joel Spolsky는 다른 고급 언어보다 C 학습에 대한 권장 사항 을 작성 했습니다 . 그의 주장은
"고급 언어로 효율적인 코드를 만들 수는 없습니다."
"최고의 프로그래밍 작업 중 하나 인 컴파일러 및 운영 체제에서는 작업 할 수 없습니다."
"대규모 프로젝트를위한 아키텍처를 생성한다고 믿어지지 않을 것입니다"
"왜 while(*s++ = *t++);
문자열을 복사 하는지 설명 할 수 없거나 그것이 세상에서 가장 자연스러운 것이 아니라면 미신에 기초한 프로그래밍입니다.
물론, 그가 쓴 것은 틀림없이 논쟁의 여지가 있지만 IMHO의 많은 주장은 오늘날에도 여전히 유효합니다.
컴퓨팅의 두 가지 기본 추상화는 튜링 머신과 람다 미적분학이며, C는 튜링 머신의 계산 관점을 실험하는 방법입니다. 그러나 C에는 자체 계산 모델이 제공됩니다. 따라서 C를 배우면 실제 아키텍처와는 상당히 다른 C 추상 머신의 저수준 세부 사항을 배울 수 있습니다. 내가 C에서 배운 첫 번째 것 중 하나는 "영리한"트릭을 적용하여 컴파일러를 능가하려고 시도하지 않았으며, 추세는 컴파일러에서 점점 더 최적화되고있는 것 같습니다. 다른 고급 언어와 마찬가지로 C로 작성할 때 컴파일러는 추상 C 시스템에서 수행 할 작업을 이해하고 실제 하드웨어에서 발생하도록합니다.
C를 배우는 것이 반드시 하드웨어에서 실제로 일어나는 일에 대한 좋은 그림을 제공하지는 않습니다. "C는 기계에 가깝습니다"는 "대부분의 고급 언어보다 더 가깝습니다"로 이해해야합니다. "어떻게 작동하는지"에 대한보다 정확한 그림을 원한다면 소프트웨어 아키텍처를 직접 배우는 것이 더 보람이있을 것입니다.
반면에 학습 C는 시스템 프로그래밍, 저수준 유형, 포인터 및 특히 메모리 할당에 익숙해 질 수 있습니다. 학습 알고리즘 및 데이터 구조에 관해서는 다른 언어가 아닌 C에서 학습하는 이점이 없습니다.