C++에서는 기본적으로 변수 이름의 규칙이 있다.
변수 뿐 아니라 함수, 클래스 등에 해당하는 것이다. C++에서 무엇인가 구별을 해야하는 것들은 이름이 있다.
이름이라는 것은 사람이 부르는 것이고 이것을 컴파일러 입장에서 파악하는게 중요하다.
컴파일러는 변수의 이름을 식별자(identifier)라고 한다.
사람은 눈앞에 있는 소스코드만 머리속에 들어있지만 컴파일러는 C++ 프로그램을 실행시킬 때 무수한 식별자를 사용한다. 심지어 hello world 하나 출력할 때도 보이지 않는 코드 속에는 수많은 식별자들이 존재한다.
만약 소스코드 안에 변수의 이름으로 컴파일러가 사용하는 식별자를 사용한다면 컴파일러는 프로그래머에게 되묻지 않을 수 없을 것이다. 이 식별자가 당신이 말하는 식별자가 맞나요? 라고 친절히 물어보면 좋겠지만 컴파일러에게 그런 능력 같은 것은 없다. 그냥 특별한 식별자들은 사용하지 못하게 하는게 컴파일러 입장에서는 편하다.
그런 식별자들을 모아놓은 것을 C++의 키워드 혹은 예약어라고 한다. (Keywords, reserved words)
쉽게 말해 정수형 변수를 정의할 때 쓰는 int 라던지 반복문을 돌릴 때 사용하는 for 같은 것이 키워드이다. 이들을 변수 이름으로 사용할 수 없다. 컴파일러는 for를 반복문으로 해석하기 때문에 사용자가 for 라는 변수를 사용하면 충돌이 일어난다. 키워드를 식별자로 사용하려고 하면 컴파일 자체가 불가능하게 되어있다.
C++의 키워드는 총 100여개 정도 되는데 int, short, char, include, define 등이 키워드이다. 시간이 지나 C++ 컴파일러 표준이 업데이트 되면서 추가된 키워드도 있다. 아래 웹사이트에서 확인이 가능하다.
Reserved keywords in C++? (tutorialspoint.com)
* 변수는 키워드를 사용하지 않는다.
* 변수는 영문자, 숫자, 밑줄(_) 문자만 사용할 수 있다.
* 숫자를 변수이름 첫 문자로 사용할 수 없다.
* 변수 이름은 대소문자를 구분한다.
여기까지가 컴파일러가 금지하는 것이다. 이 규칙을 지키지 않으면 컴파일 자체가 안된다. 이 부분은 어렵지 않다. 코드를 실행하다보면 컴파일러가 출력하는 에러메시지에서 충분한 설명을 확인할 수 있다.
여기까지는 쉽다. 이 정도의 약속을 지킬 수 있다면 C++의 문법을 안다고 할 수 있다.
변수 이름 짓기의 진짜 어려움은 다른 곳에 있다.
-> 두개의 밑줄 문자로 시작하는 변수이름은 컴파일러와 리소스가 사용하기로 예약되어 있다.
-> 하나의 밑줄 문자로 시작하는 이름은 컴파일러와 리소스가 전역 식별자로 사용하기로 되어 있다. (global identifier)
-> 변수 이름의 길이에 제한이 없다. (플랫폼에 따른 제한은 있을 수 있다, 임베디드 같은 소형 환경)
ANSI C99 (1999년 ANSI 제정 표준) 에서는 63개 문자를 유효한 것으로 처리한다. (영문 기준)
밑줄 두개 __ 나 한개 _ 를 사용해도 컴파일러가 알려주지는 않는다. 컴파일러가 사용하기로 되어 있기 때문이다. 그래서 __ 로 식별자를 잘못 정의하면 예측하지 못한 결과를 얻을 수 있다. __ 을 사용하는 경우 보통 #ifndef 전처리기로 확인 후에 사용할 수 있다.
* 아래에서 실제 변수의 예를 한번 보자. 아래는 모두 변수의 예이다. // 주석처리한 것은 동작하지 않는다.
나머지 변수들은 모두 컴파일에 통과한다.
Cpp 기준은 C++17(2017년도) 을 통과한다.
int food;
int Food;
int FOOD;
int Food123;
// int char;
// int 123food;
// int @food;
// int fo od;
// int food-tech;
int Char;
int __Food;
int _Food;
int theBestOftheBest;
int king_of_the_world;
int Thereareatotalof95reservedwordsinCplusThereservedwordsofCplusmaybeconvenientlyplacedintoseveralgroups;
모든 변수의 이름이 한 단어라면 좋겠지만 항상 그렇지가 않다.
변수 '아빠'를 지으면 '아빠의 친구', '아빠 직장' 이라고 지은 일도 있을 것이다.
그럴 때 변수 이름을 어떻게 하면 좋겠는가?
변수는 보통 소문자로 지은다. 다음 단어에는 대문자를 쓰거나 밑줄로 구분한다.
1. 아빠
char* dad;
2. 아빠 친구
char* dadFriend;
char* friendOfDad;
char* dad_friend;
단순히 봐도 다양한 조합이 나올 것을 예상할 수 있다. 이것을 프로그램안에서 막 섞어쓰면 가독성이 떨어진다.
프로그램은 컴파일러가 해석하지만 사람도 읽는 것임을 생각하여 가독성이 좋은 방식으로 작성되야 한다. 코드는 곧 문서다. 사람이 읽을 수 있어야 한다.
그러면 어떤 스타일로 작성해야 하는가?
여기서 많은 프로그래머들이 각자의 입장과 호불호가 있다. 우리가 오른손잡이에게 왼손으로 밥을 먹으라고 하면 매우 불쾌해할 뿐 아니라 실제로 서툴게 먹게 된다. 뭐냐면 서로의 개인 취향이고 또 실제적인 효율이 차이나는 부분이니 건들지 말아야 하는 부분이다. 세상에 꼭 이렇게 해야한다는 법은 없지만 일반적인 룰은 따를 필요가 있다.
일반적으로 많이 사용하는 방법을 모아놓은 것을 네이밍 컨벤션(naming convention) 이라 하는데 여러가지가 있다.
카멜표기법 camelCase, 파스칼표기법 PascalCase - 제타위키 (zetawiki.com)
언어마다 차이가 있을 수 있고 한 프로그램 안에서 변수, 함수, 클래스 등에도 차이가 있다.
예를 들어서 변수과 함수는 카멜표기법, 클래스는 파스칼 표기법으로 한다던가. 자바의 API 중에는 그런 것들이 많다.
꼭 그렇게 변수면을 지어야 작동하는 것은 아니지만 일관성을 가진다는 것은 중요하다.
파이썬의 경우는 좀 더 다양한 것 같다.
파이썬은 컴퓨터를 전공하지 않은 사람들도 광범위하게 사용하다 보니까 그런 것 같으나 PEP8 이라는 코드를 할 때 권장하는 기준이 있다.
(강제하는게 아니기 때문에 온라인의 많은 소스코드를 찾다보면 차이점을 발견할 수 있을 것이다.)
코딩을 잘하기 위해서 자신만의 기준을 세우는 것은 중요하다.
개인취향으로 이야기 하면 현재의 코드는 대부분 오픈소스로 운영되고 있다는 것을 감안해야 한다. 하나의 틀에 전 세계의 모든 소스 코드 작성방식을 하나로 통일하려는 생각은 무리라고 생각한다. 많은 사람들이 같은 사고를 하도록 교육받은 사람들은 적응하기 힘든 생각일 수도 있다.
그러나 세상은 바뀌어 왔고 앞으로도 변화한다. 세상이 바뀐다는 것은 사람이 바뀐다는 말과도 같다. 타인의 사고에 대하여 어느 때보다 관용이 필요한 시대다. 그 이유는 자신의 틀을 깨고 타인을 본보기로 삼아 발전시키기 위해서다
디지털 시대 소스코드를 대하는 자세에 옛 성현들의 지혜를 빌리면 좋을 것 이다.
자신의 코드 규칙에 대하여는 엄격하고 타인의 코드에 대해서는 관대하다면 빠른 발전을 할 수 있을 것이다.
즉 자신의 코드는 겸손하게 유지하고, 타인 코드를 높여줘라.
어디서 들은 이야기 같다. '자신에게는 엄격하고 타인에게는 관대하라' 는 말을 적용해본다.
그 말은 자신이 코드를 작성할 때는 아주 심혈을 기울여 엄격하게 해서 타인이 봤을 때 이의가 없도록 하는데 힘쓰는 것이요. 타인의 코드를 분석할 때는 다소 모난 곳이 보이더라도 너그럽게 넘어가도록 평소에 훈련을 하라는 뜻이다.
본인 코드의 가독성을 높이는 것은 노력이 필요한 일이고,
타인 코드의 해석력을 높이려면 또 노력이 필요하다.
그냥 내 코드가 잘 안 읽히는 것은 귀찮아서 그렇게 한거야 라고 변명하거나,
당신이 써놓은 코드는 거지같아서 읽기 힘들어 (shit code)
라고 이야기 하는 것은 쉬운 일이다.
하지만 자신의 발전을 위해 사용하는 것은 쉽지 않다. 그 만큼 가치 있는 일이다.