C 언어 | C 언어 입문 | 수식 및 계산
간단한 산술 및 대입, 증가 연산에 대해 설명한다.
산술식
컴퓨터는 인간처럼 자유롭게 말을 말하거나, 논리적으로 물건을 추론하는 것에는 좋지 않다 (무엇보다, 이것은 문서 작성 시점인 2002년경의 이야기이며, 변화하는 이 분야에서 항상이 상식이 통용된다고는 않지만…). 그 대신 인간에 비해 컴퓨터는 계산에 좋다. 인간에게 계산을 시키면 몇 년이 걸릴거 같은 난해한 계산도 현대의 컴퓨터는 순식간에 대답을 낸다. 암산 챔피언이라도 컴퓨터의 계산 속도에 따라갈 사람은 없다. 컴퓨터가 하는 그 계산은 프로그램의 산물이다. 컴퓨터는 계산이 특기라서 이를 프로그래밍에서 사용하지 않을 수는 없다. 결국은 계산 없이 프로그램은 성립되지 않는다.
계산을 위해서는 먼저 식을 만든다. 여기서 말하는 식은 기본적으로 수학에서 사용되는 “식"와 같은 의미이다. 식은 피연산자와 연산자로 구성되어 있다.
피연산자 연산자 피연산자 ...
그럼 “연산자(operator)“이란 무엇일까? 연산자는 한마디로! “더하기"와 “빼기"로 사용되는 수학 기호 +, - 등이다. 이것들은 앞에서 대입 연산을 하였기에, 이미 이해하고 있을 것이다. A = B
라는 표현식은 A와 B는 피연산자와 =라는 연산자로 구성되어 있다. 주의해야 하는 것은 컴퓨터에서는 ÷ 기호와 × 기호를 계산에 사용하지 않는다. 나누기(÷)는 / 기호를 곱하기(×)에는 * 기호를 사용한다. C 언어에서 사용되는 산술 연산자는 표1과 같다.
표1 산술 연산자
연산자 | 의미 |
---|---|
+ | 추가 |
- | 빼기 |
* | 곱셈 |
/ | 나누기 |
% | 나머지 |
= | 대입 |
연산자가 필요로 하는 피연산자의 수를 항이라고 하고, 이러한 연산자는 좌우에 맞게 두 피연산자가 필요하므로 이항 연산자라고 한다. 이 밖에도 피연산자를 하나만 요구하는 단항 연산자와 피연산자 3개를 필요로하는 3항 연산자라는 것도 존재한다.
C 언어의 결과는 항상 결과의 얻는 대상이 필요하다. 그것은 대입 연산자를 사용하여 변수를 받아도 상관 없고, 함수의 인수 등으로 건네 주어도 상관없다. 어쨌든, 결과를 뭔가를 받지 않으면, 계산하는 의미가 없다.
코드1
#include <stdio.h>
int main() {
int op1 = 0 , op2 = 0;
printf("두개의 숫자를 입력해 주세요. >");
scanf("%d %d" , &op1 , &op2);
printf("%d + %d = %d\n" , op1 , op2 , op1 + op2);
return 0;
}
코드1은 두 숫자형 변수 op1과 op2에 scanf() 함수를 사용하여 값을 입력한다. 그 후에 printf() 함수를 사용하여 두 값을 더한 결과를 출력한다. 예를 들어 8과 16라는 값을 입력하면 그 결과는 8 + 16 = 24
로 출력되는 것이다.
연산 결과는 대입식을 이용하여 다른 변수에 저장할 수 있다. 연산 결과를 화면에 표시하기만 한다면 코드1과 같이 인수로 함수에 전달하기 직전에 계산하는 방법으로도 괜찮지만, 연산 결과를 저장해야 할 경우 대입식을 사용한다.
코드2
#include <stdio.h>
int main() {
int op1 = 0 , op2 = 0 , op3;
printf("두개의 숫자를 입력해 주세요. >");
scanf("%d %d" , &op1 , &op2);
op3 = op1 * op2;
printf("%d * %d = %d\n" , op1 , op2 , op3);
return 0;
}
코드2는 변수 op3에 op1과 op2의 곱한 결과를 대입하고 있다. 연산 결과를 여러 번 프로그램에서 사용하는 경우, 그 때마다 계산을 반복하는 것은 CPU의 낭비되기 때문에, 계산 결과를 저장하고 사용하는 것이 좋다. 참고로 계산하는 변수와 대입하는 변수로 같은 것을 사용해도 문제는 없다. 예를 들어 op1 = op1 * op2
로 먼저 op1 * op2
가 계산되기 때문에 결과에 문제는 없다.
연산자의 우선 순위는 수학 계산 순서와 동일하다. 단순히 왼쪽에서 오른쪽으로 계산되는 것은 아니기 때문에 주의해야 한다. 예를 들면 2 + 2 * 3
이라는 수식이 있을 경우, 먼저 2 * 3
이 계산되고, 그 후에 2 + 6
이 계산된다. 계산 순서를 변경하려면 수학 마찬가지로 괄호를 넣는다. 이 경우, 뎃셈을 먼저하고 싶은 경우 (2 + 2) * 3
와 같이 함으로써 먼저 2 + 2
가 계산된 후에 4 * 3
가 계산된다.
코드3
#include <stdio.h>
int main() {
printf("2 + 2 * 3 = %d\n" , 2 + 2 * 3);
printf("(2 + 2) * 3 = %d\n" , (2 + 2) * 3);
return 0;
}
코드3의 실행 결과를 보면, 괄호를 사용하지 않는 경우는 뎃셈보다 곱셈이 먼저 계산되고 있다. 괄호로 뎃셈 부분을 묶어서 먼저 2 + 2
가 계산되고 있는 것을 확인할 수 있다.
또한 지금까지의 프로그램은 변수끼리를 계산하고 있었지만, 변수와 상수 또는 상수끼리라도 형태에 호환된다면 문제는 없다. 상수끼리를 계산한 경우에는 컴파일러가 컴파일시에 연산 결과를 예상할 수 있기 때문에 기계어로 변환된 때에는 최적화된다.
복합 대입 연산
통상적으로 대입 연산자 =를 단순 대입이라고 한다. 이 외에 계산 및 대입을 동시에 하는 연산자가 존재한다. 예를 들어 op1 = op1 + op2
라는 계산을 할 경우, 이를 op1 += op2
로 기술될 수 있는 것이다. 이와 같은 다른 연산자와 단순 대입을 결합한 대입 연산자를 복합 대입이라고 한다. 산술 및 대입을 동시에 대입 연산자는 표2와 같이 정리할 수 있다.
표2 - 복합 대입 연산자
연산자 | 의미 |
---|---|
+= | 더하고 대입 |
-= | 빼고 대입 |
*= | 곱하고 대입 |
/= | 나누고 대입 |
%= | 나머지 대입 |
코드4
#include <stdio.h>
int main() {
int op1 = 0 , op2 = 0;
printf ( "삼각형의 밑변과 높이를 입력하십시오. >");
scanf("%d %d" , &op1 , &op2);
op1 *= op2 / 2;
printf("삼각형의 면적 = %d" , op1);
return 0;
}
코드4의 식 op1 * = op2 / 2
는 op1 = op1 * (op2 / 2)
와 같은 계산과 동일하다고 생각할 수 있다.
증가 및 감소
지금 단계에서는 생각하기 어려울지도 모르지만, 많은 프로그램은 현재 변수에 1을 가산 또는 감산하는 것을 자주한다. 이 때, 통상적으로 var = var + 1
또는 var += 1
로 기술하는 것을 생각해내는 것이다. 물론 이것도 틀린 것은 아니지만, C 언어에서 이러한 작성은 일반적으로하지 않는다.
C 언어는 현재 변수가 보유한 값에 “1 더하기”, “1 빼기” 전문 연산자가 존재한다. 그것이 증가 연산자와 감소 연산자이다.
증가 연산자
변수명++
감소 연산자
변수명--
++가 증가 연산자이다. 그 변수가 현재 들어있는 값을 1 증가한다. –는 감소 연산자이다. 증가와는 반대로 그 변수가 현재 들어있는 값을 1 감소한다. 즉, var = var + 1
은 var ++
를 var = var - 1
는 var--
로 기술할 수 있다.
코드5
#include <stdio.h>
int main()
{
int iVar1 = 0 , iVar2 = 0;
iVar1++;
printf("증감 연산자 후에 var1 = %d\n" , iVar1);
iVar2--;
printf("감소 연산자 후에 var2 = %d\n" , iVar2);
return 0;
}
이 프로그램은 0으로 초기화된 변수 iVar1과 iVar2를 각각 증가, 감소하고 화면에 표시하도록 하는데 있다. 예상했던대로 증가를 하면 1증가하고, 감소를 하면 1감산된 결과가 표시된다.
증가 연산자와 감소 연산자는 두 가지 존재한다. 코드5는 후위 연산자라는 것을 사용하고 있는데, 이 밖에 전위 연산자라는 것도 존재한다. 각각 후위 증가 연산자, 후위 감소 연산자, 전위 증가 연산자, 전위 감소 연산자라고 한다.
예를 들어, 전위 증가 연산자 ++var
와 같이 변수 앞에 연산자를 놓는다. 후위와 무엇이 다른가하면, 식의 결과가 다르다.
전위 증가 연산자
++변수명
전위 감소 연산자
--변수명
후위 연산자는 변수를 사용하고 1 가산한다. 이에 대해, 전위의 경우 최초에 1을 더한 다음 변수를 사용한다. 코드5와 같이 증가 또는 감소뿐만 문장이면 전위에서도 후위도 결과는 동일하지만 복잡한 다항식에서 증가 연산자와 감소 연산자를 사용한 경우 영향이 알 수 있다.
코드6
#include <stdio.h>
int main() {
int iVar1 = 0 , iVar2 = 0;
printf("후위 증가 연산자 = %d\n" , iVar1++);
printf("전위 증가 연산자 = %d\n" , ++iVar2);
printf("iVar1 = %d iVar2 = %d\n\n" , iVar1 , iVar2);
printf("후위 감소 연산자 = %d\n" , iVar1--);
printf("전위 감소 연산자 = %d\n" , --iVar2);
printf("iVar1 = %d iVar2 = %d\n\n" , iVar1 , iVar2);
return 0;
}
이 프로그램은 인수에 값을 전달하기 전에 증가 및 감소를 실시하고 있다. 이 때, 전위와 후위에서 어떻게 다르게 동작하는지 확인하자.
실행 결과를 보면, 전위의 경우는 증가나 감소를 실시한 후에 함수에 값을 전달하고 있지만, 후위 경우 화면에 값이 표시된 후에 사용되는 것을 알 수 있다. 최종 결과는 동일하지만 이처럼 함수의 인수와 다항식으로 증가 또는 감소를 지정하는 경우는 매우 중요한 문제이다.
즉, 후위 연산자의 경우는 printf() 현재의 변수 값을 전달하고 변수를 증가하고 있는 것이다. 따라서 최초의 증가는 변수의 값 0을 전달하고 증가하고 있다. 최초의 printf()가 표시한 값은 0이지만, 그 후에 iVar1의 값이 증가되어 있기 때문에 1로 된다.
전위의 경우, 증가/감소하고 값을 함수에 전달되기 때문에 printf() 함수가 받는 값은 이미 계산된 후이다.
그래서 만약 x = var++
라고 하는 계산을 하는 경우에 주의해야 한다. x에 전달된 값은 var의 값이며, 그 후에 var가 증가되는 것이다. var 증가하고 x에 var의 값을 전달하려면 x = ++var
로 기술되어야 한다.