C 수업 들으면서 C의 한계도 조금 느꼈고, 자바와 왜 지금과 같이 발전했는지도 조금은 느낄 수 있었다. C 수업 들으면서 궁금했던 점 몇 가지 공유해 본다. 각각에 대해 대충 궁금한 점은 풀렸는데 다른 사람들은 어떻게 생각할까?
- C는 프로젝트에 main function을 하나 이상 가질 수 없다. 물론 빌드에서 제외하면 가능하다. 하지만 빌드하는 전체 소스에서 main function은 하나여야 한다. 하지만 java는 각 클래스마다 하나의 main method를 가질 수 있다. 왜 C는 하나 밖에 가질 수 없을까?
- C는 함수명이 같으면서 인자가 다른 함수를 가질 수 없다. 즉, 자바의 오버라이딩이 되지 않는다고 한다. C를 설계할 때 왜 이렇게 설계했을까?
- C의 type에서 int는 4byte, long도 4byte, long long은 8byte이다. 과거에는 int가 2byte였다고 한다. 그 이유는 뭘까? 그리고 이후에 왜 4byte로 변경되었을까?
- 짐작하건데 16bit에서 32bit로 넘어 오면서 기본 int 단위가 4byte가 됐으리라 생각한다. 그럼 64bit로 발전해 가고 있는 지금은 어떻게 되는거지? int는 8byte, long은 4byte, long long은 8byte가 되는건가? 그럼 long long long이 나와서 16byte 처리를 해줘야 되는 건가? 설마 int와 long의 byte가 역전되지는 않겠지? 신입사원이 연봉이 올라가면서 기존 2,3년차 선배의 연봉을 역전하는 사태처럼 말이야. 암튼 64bit로 발전해 가고 있는 시점에 C는 어떻게 발전해 갈 것인지 궁금하네. 다른 언어도 마찬가지고...
-
https://www.facebook.com/javajigi/posts/229720613835567 에서도 이와 관련해 좋은 답변들을 많이 주셨네요.
4개의 의견 from SLiPP
1]번은 제가 보기에는 JVM에서 돌아가는 것과 실제 바이너리의 차이 때문이기도 합니다. 실제 실행파일이 실행될 때, entry point가 있는데, 이것들이 최초 파라매터를 처리해서 실제 실행파일의 entrypoint를 호출하게 되고, 이게 보통 main으로 지정되어 있어서 그렇습니다. 자바도 jvm 파라매터로 시작할 main을 지정해줘야 하는것과 비슷해지는 거죠.
2] C가 최초에 단순히 어셈블러로 거의 1:1 매칭을 해주기 위해서가 아닐까 싶습니다. C++만 되어도 오버라이딩이 들어가는 것을 보면, 최대한 단순하게 만들고 싶었던것으로 보입니다.
3] 짐작하신대로 CPU 내부의 Register 크기에 따라서 변경하는 것이 원칙이었는데, 32bit에서 int가 4byte로 너무 많이 사용되어서, 64bit로 가면서 int를 8바이트로 바꿔버리면 문제가 생긴다고 생각해서 long 이 8바이트로 변경되었습니다. 다만 원칙적으로는 typedef를 이용해서 16bit, 32bit, 64bit를 기본 형태가 아니라 uint16_t, uint32_t 형태로 정의해서 사용하는 것이 좋은 방법입니다. ㅎㅎㅎ
1) Name space가 없기 때문이지요. C에선 모든 함수가 전역 함수라서... main 뿐 아니라 모든 함수가 단 하나만 있어야 하죠. 그리고 최초의 OOP 언어라는 시뮬라 67에서부터 객체는 모두 독립된 단위 프로그램입니다. 의존성이 있어서 복잡할지는 몰라도 독립적으로 돌아갈 수 있어야 하죠. 2) 강대명님 설명에 100% 동의. asm 코딩 좀 해본 사람은 C 코드를 보면 asm 코드가 보입니다. 쉽게 말해서 C는 고급 어셈블러죠. 3) int = word 입니다.
C언어는 정적인 언어이죠.
함수 호출시 어떤 함수가 호출될 것인지를 컴파일 타임에서 정확히 알 수가 있죠. 반대로 생각하면, 컴파일 타임에서 정확히 알려고 한 이유는 C언어가 만들어질때 상황으로는 어쩔수 없는 현실이었다고 생각합니다.
앞의 몇분이 말씀한것처럼 C언어는 어셈블리를 대체하기 위한 고급언어였기 때문이죠. fupfin님 말씀대로 고급어셈블리라고 말할수 있을 것 같습니다. (그나저나 멋진 표현이네요. 고급어셈블리.)
오버로딩의 경우는 컴파일시 정확히 함수를 매칭해주는 것이 아니라 실행시에 메소드를 찾으려는 방법이죠. 컴파일 타임에서는 해당 메소드가 정확히 어떤 메소드가 호출될지 알수가 없죠.
예를 들어 print(Object a) 라는 메소드가 있고 print(A a) 라고 있을 경우
public void execute(B b){ print(b); }
위의 소스가 컴파일 타임에서는 어떤 print메소드가 호출될수 없는 거죠.
즉 C언어는 어셈블리를 대체하는 목적으로 만들어진 것이라면 시뮬라부터 시작된 객체지향 언어는 객체지향 특성을 구현하기 위하여 오버로딩, 오버라이딩이란 개념이 등장한거죠. 그러면서..... C언어와는 다르게 정적으론 이런 개념을 구현할 수없고 동적으로만 구현할 수 밖에 없었던 거죠.
그래서 C언어가 자바같은 객체지향 언어보다 함수 호출속도가 빠른것이죠.
의견을 남기기 위해서는 SLiPP 계정이 필요합니다.
안심하세요! 회원가입/로그인 후에도 작성하시던 내용은 안전하게 보존됩니다.
SLiPP 계정으로 로그인하세요.
또는, SNS 계정으로 로그인하세요.