이 세상에는 수없이 많은 프로그래밍 언어들이 있고 각자의 영역에서 유용하게 사용되거나 아니면 범용적으로 뭐든지 가능한 프로그래밍 언어들로 나눠지는데 두 그룹의 목적이 서로 다르니 그 어떤 프로그래밍 언어가 등장해도 완전한 통합은 불가능하다는게 큰 문제임. 예를 들어 운영체제/시스템 프로그래머가 웹 쪽으로 확장하려고 하면 C 언어를 그대로 사용하긴 어렵고 그 반대도 마찬가지이지. 결국 모든 프로그래밍 언어들은 하나로 통합되지 않고 각자의 영역에서 사용되거나 범용적으로 사용되는 지금의 양상을 그대로 유지하게 될 거라고 예측함.
디어 에스더에서나 볼법한 시(C가 아닌 문학적인 의미에서 시)는 걷어내고 본문으로 들어가자면 내가 사용하는 프로그래밍 언어들(사실상 C 원툴이지만)에 대해 느끼는 공통적인 불만점이 상당히 많음. 그것은 문법 구조로 해결할 수 있는 부분들도 있고 아예 언어 설계적인 측면에서 잘못되었다고 보는 것도 있음. 그런 불만들을 신세한탄식으로 풀어볼려고 함.
1. 문법 관련 불만점들
(1). 문법에 예외 규칙이 상당하다.
가장 큰 불만은 C에서 두드러지는데 통일된 몇가지 규칙이 있긴 하지만 극소수이고 대부분은 상황에 따라 달라진다. 일단 lvalue, rvalue 규칙들이 많은 불만 사항중에 하나. 예시로 거의 대부분의 프로그래밍 언어들은 수식에서는 다 똑같다. =를 기준으로 왼쪽은 객체(또는 대상체) 오른쪽은 객체 또는 값이 올 수 있음. 반대로 말하자면 우항에 있는 계산 결과가 좌항에 저장된다고 볼 수 있음. 그런데 대부분의 언어에서 글을 읽는 방향과 좀 차이가 있다. 보통 왼쪽 위부터 오른쪽 아래로 읽어나가는데 다른 구문들은 그렇게 읽히지만 수식만 예외적으로 우항을 먼저 읽고 좌항에 그게 저장되는 논리로 생각해야 함. 단순 스타일적인 문제로만 치부하기에는 거리가 멀다. (원래 내가 사용하던 중괄호 스타일은 Allman 스타일이였지만 협업 프로젝트를 한번 진행해보고 나서부터는 바로 K&R 스타일로 바꾸었던 적도 있을 정도로 스타일에 민감하지 않음.) 내가 스타일에 민감하지 않았는데 수식을 읽는 순서는 좀 이상하다고 생각이 든다.
(2). 세미콜론의 문제점.
다행히도 세미콜론은 통일된 규칙이 있어서 어렵지 않게 이해할 수 있다. 이 규칙을 제대로 설명해주지 않는 책이 많아서 문제이지만. if, while 등의 구문들은 소괄호로 둘러싸인 조건 수식이 오고 난 뒤에는 반드시 수식이 와야한다. 그래서 세미콜론이 붙는 것임. 중괄호로 둘러싸인 블록이 오는 것은 세미콜론을 쓰지 않아도 되는 이유는 중괄호 자체가 수식의 범위를 표현해주기 때문에 없어도 되는 것. 그런데 참 어이없게도 예외가 하나 존재한다. 함수와 사용자 정의 타입들. 둘다 중괄호 수식만을 인정하지만 함수는 세미콜론으로 끝나지 않는 중괄호고 사용자 정의 타입들은 무조건 중괄호로 끝나야 한다. (타입 선언의 경우에는 세미콜론으로 끝나는 중괄호가 아니라 그냥 수식이지만 중괄호가 들어가는 정의 수식부터 문제가 생김. 이걸 모르고 메인 함수 앞에 구조체 선언을 하고 세미콜론으로 끝내지 않으면 함수가 종료할때 문제가 생길 가능성이 높다.) 아예 세미콜론을 사용하지 않거나 최소한 통일된 규칙을 제공하였으면 좋지 않았을까?
(3). 포인터와 배열.
내가 지금까지 읽어왔던 설명중에서 포인터와 배열을 표준에 맞으면서 쉬운 설명을 본적이 없다. 사실 나도 이 두 타입에 대해 제대로 설명하지 못한다. 그 만큼 초보자에게 큰 장벽이라는 뜻. 문제는 초보자가 아니라 고수도 가끔 포인터나 배열을 잘못 사용해서 프로그램을 강제종료시키거나 의도치 않은 동작을 하는 경우가 상당히 많다는 것임. 그것은 포인터와 배열에 대해 심도있는 이해를 한다고 해결이 되는게 아니라 그냥 C 스타일의 포인터와 배열은 위험성을 가지고 있는 문법이다.
사실 포인터와 배열은 하드웨어에 둔한(혹은 덜 민감한) 방식이라고 생각하기에 위험하기도 하고 불편하다고 생각해본 적이 있음. 어떤 기계가 항상 동적 메모리 할당을 지원하는 것도 아니고 정해진 데이터 영역만 써야하는 경우가 많은데 배열은 이 고정적인 데이터 영역을 사용하는데 편하고 포인터는 메모리 할당을 지원하는 기계에서 사용하기 편하다는 점. 그리고 결국 배열은 포인터로 추상화될 수 있고 둘이 비슷하게 취급될 수 있다는 점이 하드웨어에 대한 부담을 덜어준다고 생각함.
(4). 문자와 문자열의 차이.
문자는 대응되는 값을 가진 하나의 문자, 문자열은 문자가 연속적으로 할당된 공간의 첫번째 요소를 가리키는 대상체라고 가르치는 책이 많았다. 틀린건 아니지만 좀 이해하기 어렵다. 문자가 저장된 대상체가 널 문자를 포함할 수도 있고 이게 메모리에 저장되면 바이트 순서에 따라 다르겠지만 문자열이 되는 경우가 상당하다. 그리고 문자열에 널 문자가 없으면 문자열로 취급되지 않는다. 또 포인터와 배열에 대입하는 문자열이 다르다는 점도 초보자가 이해하기 어렵다.
(5). 블록 구조로 인한 문제점들.
한 블록 안에서 변수가 선언될때 바깥에 있는 같은 이름의 변수가 이미 존재하면 바깥에 있는 변수는 숨겨지는데 이 규칙이 애매하다. 전역 변수를 함수 안에서 선언된 변수로 가릴 수 있고 그게 안되고 오류를 출력하는 경우도 있다는게 문제점.
글자수 제한 때문에 여기까지만 설명하고 언어 설계상 잘못된 부분들은 다음에 또 작성해볼 생각임.
다른건 모르겠는데 1번은 서양하고 동양 언어 차이임
그냥 C언어 불만이네
대부분은 C 계통이니 언어 전반적인 불만점인데 C가 가진 적폐 수준의 문법이 너무 많아서 그렇게 보이는거임.
2 사용자 정의 타입은 원래 struct TAG { } 변수이름;임. 그래서 세미콜론이 붙음
함수도 마찬가지로 타입 정의는 아니지만 정의에는 포함되기 때문에 왜 이녀석만 세미콜론이 붙지 않는다고 뭐라 할 수는 있을듯
rust
Redox로 통합이 가능할까?
함수 선언에는 세미콜론 붙는다. if문이나 다른 제어문의 범위처럼 사용되는 거지 그러면 예외가 아님
그럴수도 있겠네
문자열에 종료문자 없다고 문자열로 취급하지 않는 것은 아님. 단지 버그를 일으키는 문자열일 뿐.
그래서 잘 고안된 라이브러리의 문자열 받는 함수들은 문자 갯수도 인자로 받음
1번. 수학 수식 표기할 때, 새로운 이름을 정의 할때 x=4 이런 식으로 하는거에 익숙해서 공감가지 않음 2번. 무슨 얘기인지 모르겠다. 일단 수식이라고 하는 건 statement를 말하는 거지? 메인함수 종료할 때 문제 생긴다는 것도 무슨 얘긴지 모르겠어.
3. 무슨 자료를 읽었길래 포인터와 배열 개념에 혼동이 온건지 모르겠지만 내가 처음 배울 때는 명확했다.
4번. 뭐가 문제인지 모르겠다. eos를 알 수 있어야 하는데 그걸 널문자로 하는 것에 뭐가 문제가 있지? 5번. 애매하지 않음. 같은 이름, 같은 타입이면 surrounding block의 변수가 가려진다. 매우 간단하다고 생각해. 이걸 남용해서 헷갈려진다? 애당초 변수네이밍을 제대로 하면 됨
그리고 몇몇 논리에서 초보자가 받아들이기 어렵다. 이런 얘기가 많은데 c는 초보자가 이해하기 쉬우라고 만든 언어가 아냐.
1번의 수학 수식 표기는 x를 4로 정의하는게 아니라 둘이 같다고 하는거임. 프로그래밍의 등호는 같다고 하는게 아니라 대입이기 때문에 수학의 그것과는 좀 거리가 있음. 예를 들어 a=b로 정의했으면 수학에서는 b 자리에 a가 들어가도 되지만 프로그래밍은 아닐수도 있기에 직관적이진 않다고 설명한 것. 2번은 구조체를 반환하는 함수가 가상의 구조체 포인터를 인자로 전달하는 경우가 많은데 argc와 argv의 값을 이용하는 메인 함수라면 사용할때 문제가 발생할수도 있고(인자의 저장 순서는 다를 수도 있으니) 종료할때 구조체를 반환해서 가상의 포인터에 전달하는데 그 값으로 정수형 값이 전달되니 잘못된 포인터 접근이 일어나서 강제종료할 수 있다고 C FAQ에서 설명했음.
1. 둘이 같다고 하기 이전에 새로운 이름을 넣음으로써 "정의" 하는 효과가 있다고 봤다. 수학 문제 풀면서 새로운 이름 추가할 때 5=x 이런 식으로 쓴 적이 없었어. 적어도 나는
3번은 포인터와 배열 개념에 혼동이 왔다고 말한적이 없음. 단지 초보자에게 설명할 수 있을 만큼의 능력이 없다고 이야기했는데 이게 왜곡된거 아냐? 너가 처음 배울때 뭘로 공부했는지는 모르겠는데 다차원 배열의 실체를 제대로 말할 수 있다면 머리가 좋은 것과 별개로 처음 배울때 명확하게 가르칠 수 있는 문서가 없다는건 맞는말이 아닐까.
2번 여전히 이해가 안가는데 그 c faq 항목 링크 부탁해
결국 1번은 글을 읽는 순서와 연관지어서 설명한 것인데 왜 왼쪽에서 오른쪽으로, 위에서 아래로 읽는데 표현식만 "a에 다음 수식을 계산한 결과를 넣어라" 라고 이해해야 하는지 모르겠다는 거야. 그냥 이 수식을 계산해서 a에 넣으라고 하는게 좀 직관적으로 읽히지 않을까?
1번. 난 수학문제 푸는 것에서 익숙함을 받았지만 넌 실행순서에서 이질감을 느낀듯. 이 정도로...
Q 2.18
http://c-faq.com/struct/retcrash.html
1번은 그렇게 넘어가고 결론은 글을 읽는 순서와 동일한 문법을 가진 프로그래밍 언어는 없을까? 라고 결론을 짓는다. 의외로 금방 답이 나올지도 모르겠어. 왜냐하면 베이직조차 역순이기 때문에. 경로의존성을 넘어서 아예 이게 표준이 되버린 것도 크고.
3번. 왜곡하려던게 아닌데 미안. 난 머리 좋은 것도 아니고, 다차원 배열의 실체는 복잡하지 않다고 생각함. 이건 아무래도 느낌의 차이인 것 같으니 공감대를 찾기 어려울듯
ㅇㅇ/ 수학에선 =를 equal로 사용하고 C like syntax에서 =는 assign으로 사용함 수학에서도 미지수하나에 assign한다고 잘못 생각하고 있는듯
난 C언어 펀더멘탈을 완독하고 나서야 다차원 배열의 실체를 알게 되었어. 그리고 설명은 노 코멘트. 복잡하지 않다는 말에 141.42135624%만큼 동의함.
c faq 링크 봤는데 저런 식으로 쓰는건 비표준 문법이다. 저걸 허용하는 컴파일러가 있긴 한데 Main 리턴값은 반드시 int 여야 하는게 표준임. int 리턴하는 main은 리턴문에서 에러날 일 없다. 이건 c가 아니라 gcc같은 컴파일러의 문제지.
다시 보니까 표준만 지키면 저런 거지같은 코드가 컴파일 될리가 없지 당장 리턴 타입이 int로 명시되어 있는데 구조체 정의가 있으면 함수에는 여전히 int가 붙고 그저 잘못된 구조체 정의 문법이라는 것만 알면 되지. 근데 저딴 코드를 GCC에서 정상적으로 컴파일한다고?
ㅇㄹㅇ// equality과 assignment의 차이는 알고 있음 단지 좌변에 l-value가 들어가는 문법을 익숙하게 느낀 원인이 수학문제를 풀던 기억이라는 것임
gcc에 비표준 문법 많아. 플래그 주면 표준 문법을 어느정도 강제 가능
GCC 비표준 문법 옛날에 다 표준화되서 없다고 생각하고 있었는데 지금도 심각한가 보네. -std=c99 옵션 정도 넣어주면 원천방지 가능함?
표준 플래그 넣는건 국룰임
님 언어 뭐뭐해봄
C 원툴이라고 했는데 대부분 C 까는거고 C++, C#(유니티 때문에 아주 잠깐), 파이썬, 루비 정도 해봄.
문자열에 대한 독특한 정의는 그것이 C의 구현이기 때문임. 당장 C++만 가도 전혀 다르게 구현한 문자열을 쓸 수 있고, 좀 더 추상화된 언어들은 문자열을 primitive type으로 쓰는 경우가 많음.
그리고 메모리에 랜덤하게 쓰여진 값이 어떤 패턴을 갖게 된다고 해서 그게 뭐다 하고 정의하는 것은 넌센스임. 코드로 예측된 범위 내에서 주소값을 통해 접근한 데이터만이 의미를 가짐.
그건 당연히 알고 있지. 근데 이 대상체의 주소를 문자열 시작 주소로도 사용할 수 있다는 점이 난 더 넌센스라고 생각하는데?
왜냐하면 C에서 문자열이란 결국 값 0으로 끝나는 공간이기 때문에, 예외가 있다면 배열에 문자열을 넣는 것? 0으로 끝나지 않는 문자 공간의 정의는 그게 문자를 저장했으면 연속된 문자고 문자열은 아니라는거지. 문자를 저장하지 않았다면 진짜 무슨값인지 알 수 없고.
길이값을 정확히 알지 못해도 일단 0에서 끝나도록 설계한 것이 C의 문자열이고, 이게 정의인 이상 납득하고 넘어가야 할 문제일 뿐임.
그래서 고랭지 농법이 나온거 같아요~ 이런 C언어의 난해함을 다 해소시켜줄~
x는 3 - dc App
이렇게 이해해 - dc App