5-1-다.대입 연산자

대입(Assignment)이란 변수에 어떤 값을 집어 넣는 동작이며 대입 연산자는 변수의 값을 변경할 때 사용한다. = 기호를 사용하며 다음이 가장 간단한 대입문의 예이다.

 

i=1;

 

i라는 변수에 1이라는 값을 대입한다. = 연산자는 우변에 있는 값을 좌측으로 대입하는데 위와같이 우변이 상수일 경우는 계산할 것도 없이 상수를 바로 좌변에 대입한다. 우변이 다음과 같은 수식일 경우는 이 수식을 계산한 결과가 좌변으로 대입된다.

 

i=2+3;

i=j+k*m;

 

i에 2+3을 더한 5가 대입될 것이다. 이런 상수 수식은 계산 결과가 상수이기 때문에 실행시에 계산되지 않으며 컴파일할 때 컴파일러에 의해 미리 계산된다. 즉 i=2+3;이라고 대입하면 컴파일러는 이 명령을 i=5;로 고쳐서 써 넣으므로 2+3이라고 쓰나 5라고 쓰나 전혀 차이가 없다. 변수가 들어가 있는 수식은 변수의 값에 따라 결과가 달라지므로 실행할 때 계산되어 i로 대입될 것이다.

좌변값

대입 연산자의 우변에는 상수, 변수와 연산자들로 구성된 계산할 수 있는 표현식이 오며 함수호출문도 올 수 있다. 하나의 결과를 계산해 낼 수만 있다면 어떤 표현식이 와도 상관없다. 대입 연산자의 좌변에는 좌변값(lvalue:left value)만 올 수 있는데 좌변값이란 대입 연산자의 왼쪽에 올 수 있는 값이라는 뜻이다. 좀 더 정확하게 정의를 내려 보면 실제적인 메모리를 점유하고 있고 그 값을 바꿀 수 있는 대상이라는 뜻이다.

i=1; 대입문에서 변수 i는 실제 메모리를 점유하고 있고 값을 마음대로 바꿀 수 있으므로 좌변값이다. 그래서 i=1; 대입문에 아무런 문제가 없다. 그러나 다음과 같은 대입식은 쓸 수 없다.

 

1=2+3;

a+b=4;

 

상수 1은 실제 메모리를 점유하고 있지 않으며 그 값이 고정되어 있고 바꿀 수 없으므로 좌변값이 아니다. 2와 3을 더한 값을 1에 대입하라니 말이 안되며 당연히 에러로 처리된다. 변수는 완전한 좌변값이 맞지만 변수로 구성된 수식은 좌변값이 아니다. 따라서 a+b=4; 대입문도 에러로 처리된다. a=4-b;는 물론 가능하다.

위의 두 대입문이 왜 에러인지는 논리정연한 설명보다 직관적으로 이해하는 것이 더 빠를 것이다. 좌변값에 대한 정의가 무척 쉽다고 생각되겠지만 나중에 진도를 좀 더 나가면 좌변값인지 판별하는 것이 점점 어려워진다. 다음 대입문을 보자.

 

char str[12];

str="STRING";

 

이 문장은 C를 처음 공부하는 사람들이 가장 많이 실수하는 부분이다. 문자 배열은 문자열을 저장할 수 있지만 이런 식으로 문자열을 대입할 수는 없다. 왜냐하면 배열의 이름인 str은 좌변값이 아니기 때문이다. 좌변값에 대해 좀 더 정리를 하자면 배열 요소는 좌변값이지만 배열은 좌변값이 아니며 포인터 변수 ptr이 있을 때 *ptr은 좌변값이지만 &ptr은 좌변값이 아니다. 배열 요소도 일단은 좌변값이지만 최종 요소만 좌변값이며 다차원 배열의 부분 배열은 배열 요소이기는 하지만 좌변값이 아니다. 이런 복잡한 얘기는 배열과 포인터에서 다시 다룰 것이므로 여기서는 대입 연산자 왼쪽에는 좌변값만 올 수 있다고 알아 두도록 하자.

연산자의 리턴값

C의 모든 연산자는 연산 후 그 결과를 돌려주는데 이를 리턴값이라 한다. 리턴값이란 원래 함수의 계산 결과를 의미하는데 연산자도 일종의 함수이므로 연산 결과를 리턴값이라 한다. 1+2라는 수식은 1과 2를 더한 결과인 3을 리턴한다. +연산자가 값을 리턴하기 때문에 a=1+2; 같은 문장이 가능한 것이다. 1+2가 더하기만 하고 끝나버린다면 a에는 아무것도 대입되지 않을 것이다. 대입문도 마찬가지로 그 결과를 리턴하는데 리턴되는 값은 대입된 값 자체이다.

연산자가 값을 리턴한다는 것은 굉장히 중요한 사실이며 이 리턴값을 이용하면 여러 가지 다양한 응용이 가능하다. i=1; 대입문은 i에 1을 집어 넣고 끝나는 것이 아니라 그 결과로 다시 1을 리턴한다. 그래서 이 대입식 자체를 다른 수식에 사용할 수 있다.

 

a=5;

b=5;

c=5;

 

이 세 개의 대입문을 좀 더 간단하게 정리하여 다음과 같이 쓸 수 있다.

 

a=b=c=5;

 

왜 이 수식이 가능한가 하면 대입 연산자가 대입된 값을 리턴하기 때문이다. 이 식은 제일 먼저 c=5를 실행하며 그 결과로 5를 리턴한다. 이 리턴값을 b가 받고 b에 5를 대입하는 식은 다시 5를 리턴하며 이 값이 다시 a로 대입된다. 최종적으로 a에 5가 대입된 후 다시 한 번 5가 리턴되는데 이 값은 사용되지 않는다.

복합 대입 연산자

복합 대입 연산자는 대입 연산자와 다른 연산자가 결합된 연산자이다. 간단한 사용예를 보자.

 

a=a+3;

 

이 수식은 원래 a값에 3을 더해 a에 다시 대입하라는 뜻이며 a를 3만큼 증가시킨다. 변수의 현재값을 기준으로 상대적으로 값을 증감시킬 때 아주 많이 사용하는 식이다. 이처럼 좌변의 변수가 우변의 수식에 포함되어 있을 때는 이것을 복합 대입 연산자로 바꿀 수 있다.

 

a+=3;

 

여기서 사용된 +=이라는 연산자가 바로 복합 대입 연산자이며 좌변의 값을 우변만큼 증가시킨다. a=a+3과 a+=3은 완전히 같은 식이되 변수명이 다음과 같이 아주 길다면 이 변수를 두 번 쓰는 것보다는 복합 대입 연산자로 한 번만 쓰는 것이 편리하다.

 

VeryLongNameVariable = VeryLongNameVariable +3;

VeryLongNameVariable += 3;

 

또한 연산 대상이 arPara[NowPara-1]->aPos[p-offset].Start 처럼 구조체와 배열, 포인터 등이 섞여 있는 아주 복잡한 표현식인 경우도 복합 대입 연산자를 쓰는 것이 편리하다. + 연산자 뿐만 아니라 산술 연산자, 비트 연산자들이 복합 대입 연산자가 될 수 있다. 연산자 x에 대한 복합 대입 연산자는 x=로 만들면 된다.

 

+=  -=  *=  /=  %=  <<=  >>=  &=  |=  ^=

 

그러나 아무 연산자나 다 복합 대입 연산자로 만들 수는 없으며 위에 보인 10개가 전부이다. 이런 복합 대입 연산자를 만나면 원래 수식을 떠올려 보면 된다. 복합 대입 연산자를 쓰면 식이 좀 더 간단해지는 반면 몇 가지 부작용이 있기 때문에 복잡한 수식에서는 사용하지 않는 것이 좋다. a+=n 정도의 간단한 수식에만 사용하는 것이 바람직하다.