프로그램이란 연속적으로 실행되는 명령어의 집합에 지나지 않는다.

 

이 단순한 명령어들이 조건에 따라 분기하여 마술과 같은 일을 만든다. 컴퓨터가 하는 일을 보고 있으면 신통방통하지만 컴퓨터가 하는 일들을 쪼개고 쪼개서 보면 결국 하나의 단위에서 출발하는 것이다.

 

문장 (Statement)

 

C++에서는 소스코드의 한 라인이 종료될 때 세미콜론 ; 을 입력한다. 이것을 문이라고 한다. (statement) 

 

아래의 문을 보면 수학식과 닮아있다. 대수학처럼 보이는데 처음 프로그래밍을 접하면 곧 큰 차이를 알게된다. 

// 변수 선언문

int a; 
int b;
int c;

// 할당문

a = 10;
b = 5;
c = a + b;

a = 10 은 수학에서 처럼 a는 10과 같다는 뜻이 아니다.

 

C++ 에서는 리터럴 상수 10의 값을 변수 이름이 a 인 메모리에 저장하라는 뜻이다. 내부적으로 숫자 10은 이진수 1010로 변환되어 메모리에 저장된다. 

 

c = a  + b 를 명령어로 표현하면 'c 에 a + b 연산결과를 할당하라' 는 뜻이다. 할당하는 명령어와 덧셈( + ) 명령어는 두개이지만 C++에서는 하나의 문으로 이루어져 있다. 세미콜론 ; 이 문과 문을 나누는 경계이다.

 

=, + 같은 기호를 C++에서는 연산자라고 한다. = 는 오른쪽에 있는 값을 왼쪽의 변수로 할당 연산을 수행하고 + 연산자는 두개의 항(이항)을 더한 값을 반환한다.

 

C++ 컴파일러는 문자 사이의 공백(White space)과 탭(tap)공백을 무시한다. 예를 들어

 

 c = a + b 는

 

c                         =                   a +

c        ;

와 같다. 컴파일러는 세미콜론을 기준으로 공백들을 제외하고 하나의 문(Statement)를 구성할 것이다.

 

둘의 차이는 인간이 알아보기 쉽냐 어렵냐의 문제다. 가독성이 낮은 코드를 만들면 자신과 타인이 읽기 어렵게 된다. 대체적으로 형식을 지켜주는게 읽기에 수월한 코드가 된다. 프로그램의 실행은 컴파일러가 해독할 수만 있으면 되지만 코드를 유지 보수하는 사람을 위해서 기본적 룰이란게 존재한다. 물론 자신만의 스타일을 개발하는 것도 C++ 에서는 막지는 않는다. 사용자에게 자유도를 주고 프로그래머가 책임을 지게 한다는 C부터의 철학이다. 그렇지 않다면 포인터같이 하드웨어에 접근할 수 있는 경로를 막아놨을 것이다.

 

그렇다고 저렇게 공백을 남용하는 프로그래머는 없겠지만... 컴파일러의 입장에서는 완벽하게 허용하는 문법이다. 컴퓨터를 잘 다루기 위해서는 컴퓨터의 사고방식을 이해할 필요가 있다. 어떤 사람이 저 코드를 봤을 때 ' 아니 이런 코드를 쓰는 사람은 제정신인가? 화가 나는구나!' 라고 말할지 모른다. 그건 사람이 반응하는 방식이고 컴파일러는 완벽하게 괜찮은 코드이다. 반면 컴파일러는 10 = a + b; 라는 문장은 깨끗하게 작성되었는데도 절대로 허용하지 않는다. 우리가 보면 대수의 일종인데 컴파일러는 거부한다.

 

컴퓨터 기술은 인간의 생각과 컴파일러 사고의 차이를 아는 것에서 출발한다. 가끔씩 아주 어린 나이부터 타고난 사람들이 있다. 10살 13살 이 어릴때 부터 인간이 사고하는 것보다 컴퓨터가 사고하는 방식에 더 익숙한 사람들이다. MS의 창업자 빌게이츠나 리누스 토발즈 같은 천재들이다. 그들에겐 매우 쉬운 것이 일반인에게는 어렵다. 한편 대중도 그들의 행보를 이해하기 쉽지는 않다. 컴퓨터의 사고방식을 이해하는 것은 단순히 학습의 문제가 아니라 가치관의 문제로도 볼 수 있다. 컴퓨터 알고리즘이 지향하는 것은 무엇인가? 인간을 위한 것인가 컴퓨터를 위한 것인가? 아니면 그 중간에 어디 쯤인가?

 

understanding computer thinking

이런 면에서 컴퓨터과학은 생각해볼 꺼리가 많다. 물론 컴퓨터의 세계에서 일어나는 모든 미시적 거시적 사건들이 진리라고만 볼수는 없다. 컴퓨터 과학은 극히 최근에 만들어진 학문이고 사람들은 아직 무슨 일이 일어나는지 모르고 있다.

 

컴퓨터를 사용해서 전세계 수많은 사람들에게 즉각적인 메시지를 전송할 수 있는 능력은 지금의 세대가 인류 역사상 유일하게 가진 힘이다. 이 엄청난 파워를 어떻게 사용해야 하는지 모르지만 어쨋든 사람들은 인스타를 하고 페이스북을 하고 있다.

 

이 시스템을 밑에서부터 떠받치고 있는 것이 C++을 비롯하여 컴퓨터에게 다양한 언어로 명령하는 컴퓨터 공학자들이다. 언어를 공부할 때는 자각을 하는게 좋다. 많은 전문가들이 특히 C++ 은 제대로된 기술트리를 타고 배운다면 절정의 언어라고 말한다.

 

절차지향적 언어와 저수준 레벨(low level)언어인 C를 계승하면서 객체지향과 일반화 프로그래밍(Generic)까지 혼합해서 사용할 수 있다. C++이 뒤로 갈수록 난해해지는 이유다. 어렵지만 C++에 공을 들여 배워나가면 머지않아 보상을 받을 언어다.

 

의지가 있으면 조급하지 않아도 된다. C언어가 조금 더 단순하니 C언어를 먼저 배워도 좋고, 처음부터 자바의 객체지향으로 시작하는것도 나쁘지 않다. 그것도 다 별로면 파이썬은 쉽게 질리지 않을 것이다. 파이썬을 시작하면 프로그래밍 언어라기 보다 놀이 처럼 시작할 수 있다. 그 옛날 애플의 BASIC과 비슷하다.

 

C++ 은 대체로 입문자에게는 권하지 않는 언어다. C++ 가르치는 강사들이 대부분 C언어 부터 강의를 하기 때문에 C++에서는 내용을 어느정도 생략하는 경향도 있다. 완전 초보도 괜찮다고 하는데 그건 그냥 하는 말 같고 C++을 배우려면 C언어부터 배우는게 정신건강에도 도움이 된다. 안타깝지만 많은 이들이 C언어를 포기한다. 보통은 위에서 이야기한 컴퓨터의 사고를 따라갈 수 없기 때문이다.

 

컴퓨터식의 사고를 습득하면 C언어의 학습 자체는 빨리 끝낼 수 있다. C언어의 학습과 C언어로 무언가를 구현하는 것은 다른 문제니까. 하지만 그 정도 단계까지 가는게 쉽지않은 사람도 있다. 어쨋든 필자는 컴퓨터를 시리어스 serious 하게 생각한다면 C언어를 추천한다. 사실 고수준(high level) 언어인 C언어가 저수준(low-level)의 모든 것을 다루는 것은 아니고 더 알고 싶다면 다른 것들도 공부해야 한다. 하지만 운영체제의 수준에서 이해하기에는 충분하다. 운영체제를 알면 컴퓨터 프로그래밍이란 건 그 위에 돌아가는 앱을 만드는 것이니까 잘 하게 된다.

 

약간 잡설이 길어졌지만 다음으로 넘어가본다.


*복합문 Compound Statement

 

복합문은 여러개의 문을 { } 중괄호로 묶는다. 아래의 복합문은 변수를 서로 바꾸는 복합문이다. (SWAP 이라 한다)

 

두개의 변수를 바꾸기 위해서는 반드시 하나의 변수가 더 있어야 한다. 어셈블리어에서는 CPU의 범용 레지스터를 사용해서 스왑할 수 있는데 고수준 언어들은 보통 레지스터를 사용하지 않는다. (C에서는 접근이 가능하긴 하다) 따라서 명시적으로 임시 변수를 하나 더 만들어서 스왑하도록 한다.

 

A가 B에게 복사하기 전에 temp에 임시 복사를 해두면 A에 B를 할당해도temp 에 A의 값이 남아있다. temp 를 B에 할당하면 스와핑(SWAPPING) 이 완료된다.

 

괄호가 쳐진 영역을 보면 하나의 구역임을 알 수 있다. 이 괄호가 갖는 의미는 나중에 함수와 클래스에서 확장된다. 지금은 이런 영역이 있다는 것을 알면 충분하다. { 중괄호를 brace 라고 한다. 앞쪽을 opening brace 뒤쪽이 closing brace다. 중괄호에는 세미콜론 ; 을 붙이지 않는다. 

{
    int temp;
    int x = 10, y = 5;
    
    temp = x;
    x = y;
    y = temp;
}

*표현식 (expression)

C++의 표현식은 값을 반환하는 모든 문장을 말한다. 숫자를 반환하면 표현식이다. 이게 무슨 말인지 혼동스럽다. 쉽게말해 숫자 3은 표현식이다. 상수인 PI(원주율)도 표현식이다. 문에 숫자를 쓰면 그것으로 표현식이 된다.

 

3
PI

 

수학에서의 식을 생각하면 이해가 안간다. 예를 들어서 원의 둘레를 구하는 아래의 공식을 보자. 좀더 편하게 한글로 영어로 써봤다. 때로는 영어때문에 공식이 어려워지니까 한글로 쓰면 한결 편하다.

//한글

원의둘레 = 2 X 파이 X 반지름

// 영어

Area of Circle = 2 x PI x radius

// C++

Area = 2*PI*r

여기서 C++의 표현식은 (2*PI*r) 이다. 리터럴 상수 2와 심볼릭 상수 PI를 곱하고 원의 반지름 r 변수를 곱하면 어떤 값을 반환하게 되어 있다. 그 반환한 값을 Area 에 할당하게 되는데 이는 숫자가 된다. = 할당 연산자는 오른쪽의 표현식의 값을 반환받아서 Area 변수에 입력한다.

 

표현식은 보통 = 할당연산자를 중심으로 오른쪽에 위치한다. 수학에서는 어떤 계산들을 하고 나면 값이 나오는데 그게 꼭 숫자가 아닐 수가 있지만 컴퓨터언어에는 반드시 값이 도출되야 한다. 값을 반환하는 식을 표현식이라 하고 함수가 값을 반환하듯이 값을 반환한다.

 

d = (a+b+c) 라는 계산을 할 때 우리는 머리속으로 직관을 사용해서 할 수도 있지만 컴퓨터에게 그건 불가능하다.

 

우선 a+b를 하고 그 결과를 CPU의 레지스터에 저장한다. 그 다음에 레지스터와 c를 더한다. 역시 레지스터에 저장한다. 그 결과값을 d의 메모리 주소를 찾아서 저장하는 것이다.

 

하나의 숫자도 스스로를 반환한다는 개념에서 표현식이고, 하나 이상의 변수를 연산자로 계산한 결과를 반환하는 것도 표현식이다. 표현식의 유용한 사용법은 C++ 학습을 하면서 더 잘 알게 될 것이다.

 


*증감연산자

증감연산자는 코드를 깔끔하게 만드는 테크닉이다.

 

하나의 변수가 있을 때 여기에 1을 더하고 싶다. C++의 변수는 자기 자신에게 더하는 기능이 없기 때문에 아래와 같은 코드가 필요하다.

int a = 1;

int temp;

temp = a + 1;

a = temp;

다행히 이 긴 코드를 한줄에 해결할 수 있도록 만들어놨다. 세가지 방법으로 가능하다. 먼저 증감연산자를 사용한다.

 

변수 a에 ++ 증가연산자 (increment)를 붙인다. 주의할 점은 앞쪽이냐 뒤쪽에 따라서 차이가 있다. 뒤쪽에 붙이면 값이 문장 제일 마지막에 증가하고 앞쪽에 붙이면 먼저 증가한다. 쉽게말해 할당연산자 = 보다 늦게 증가하느냐 마느냐의 문제다. 아래 예제를 보면 각 세미콜론 ; 이 끝나기 전에 어떤 연산이 되었는지 알 수 있다.

 

반대의 경우 -- 마이너스 두개를 붙이면 같은 방식으로 감소연산을 한다.

    int x = 10;

    cout << "x++: " << x++ << endl;
    cout << "x  : " << x << endl;

    cout << "++x: " << ++x << endl;
    cout << "x  : " << x << endl;

 

 

상당히 쾌적한 테크닉인데 앞뒤에 따른 혼동 문제가 좀 있다 보니 코드 읽기가 좀 더 힘이 든다. 그런 경우는 다음과 같은 방법도 있다.

x += 1;

x = x + 1;

x에다가 1을 누산하라는 것이다. 파이썬의 경우 증감연산자가 없고 이 방법을 사용한다.

 

CPU의 범용 레지스터에는 누산기가 있는데 C++의 변수에는 왜 누산기가 없을까? 명시적으로 CPU의 레지스터를 사용한다는 내용이 없기 때문이라 생각한다. 변수와 레지스터는 저장을 한다는 메모리라는 점에서 같지만 전혀 다른 회로를 이용하고 있다. 어셈블리어를 배운다면 누산기를 사용하는 것을 배울 수 있을 것이다. (ADD EAX 1)

 

증감연산자 사용의 포인트는 헷갈리지 않도록 코드를 짜는 것이다. 무리하게 전위화 후위를 바꿔서 사용하면 읽는 사람이 피곤할 수 있다. 그런 경우 x += 1 도 좋은 방법이다.

공유하기

facebook twitter kakaoTalk kakaostory naver band