프로그램은 CPU가 처리하는 명령어의 묶음이다. 일반적으로 연산자는 컴파일되면 명령어로 바뀌므로 연산자를 배우는 것은 명령어를 익히는 것과 같다. 연산 명령에는 연산의 대상이 되는 데이터가 필요한데 이를 피연산자라고 한다.
수학에서도 많이 사용하는 더하기, 빼기 등의 연산을 의미한다. 산술 연산자에는 더하기(+), 빼기(-), 곱하기(*), 나누기(/), 나머지(%)가 있다. 모두 2개의 피연산자를 사용하며 이 중 빼기 연산자는 피연산자를 하나만 사용할 때 피연산자의 부호를 바꾸는 역할도 한다.
대입, 더하기, 빼기, 곱하기, 음수 연산
#include <stdio.h>
int main(void)
{
int a, b;
int sum, sub, mul, inv;
a = 10;
b = 20;
sum = a + b;
sub = a - b;
mul = a * b;
inv = -a;
printf("a의 값 : %d, b의 값 : %d\n", a, b);
printf("덧셈 : %d\n", sum);
printf("뺄셈 : %d\n", sub);
printf("곱셈 : %d\n", mul);
printf("a의 음수 연산 : %d\n", inv);
return 0;
}
오른쪽 수식의 결과를 왼쪽 변수에 저장한다.
나누기 연산자를 사용할 때는 피연산자의 형태에 따라 결과가 달라지니 주의해야 한다. 정수로 연산할 때는 몫을 구하고 실수로 연산할 때는 소수점까지 구한다.
#include <stdio.h>
int main(void)
{
double apple;
int banana;
int orange;
apple = 5.0 / 2.0; // 실수와 실수의 나누기 연산
banana = 5 / 2; // 정수와 정수의 나누기 연산
orange = 5 % 2; // 정수와 정수의 나머지 연산
printf("apple : %.1lf\n", apple);
printf("banana : %d\n", banana);
printf("orange : %d\n", orange);
return 0;
}
만약 정수/실수와 같이 피연산자의 형태가 다르거나 실수를 정수형 변수에 저장하면 이야이가 복잡해진다. 추후 형 변환 연산자에서 자세히 알아가보자.
a라는 int형 변수에 1을 더하려면 a = a + 1; 이라고 쓰면 된다. 그러나 편하게 ++a; 로 간단히 표현할 수 있다.
#include <stdio.h>
int main(void)
{
int a = 10, b = 10;
++a; // 변수의 값을 1만큼 증가
--b; // 변수의 값을 1만큼 감소
printf("a : %d\n", a); // a : 11
printf("b : %d\n", b); // b : 9
return 0;
}
a = a + 1 이 ++a로 표현된다는건 증감 연산자가 대입 연산을 포함한다는 것. 따라서 피연산자의 값도 바뀐다. ++10과 같이 상수에 직접 증감 연산자를 사용할 수 없다.
전위 표기와 후위 표기
증감 연산자는 위치를 피연산자 뒤로 옮길 수도ㅗ 있다.
전위 표기는 값이 증감하고 나서 연산에 사용.
후위 표기는 연산에 사용하고 나서 값이 증감한다.
#include <stdio.h>
int main(void)
{
int a = 5, b = 5;
int pre, post;
pre = (++a) * 3; // 전위형 증감 연산자
post = (b++) * 3; // 후위형 증감 연산자
printf("증감 연산 후 초깃값 a = %d, b = %d\n", a, b);
printf("전위형 : (++a) * 3 = %d, 후위형 : (b++) * 3 = %d\n", pre, post);
return 0;
}
실행 결과는
증감 연산 후 초깃값 a = 6, b = 6
전위형 : (++a) 3 = 18, 후위형 : (b++) 3 = 15
로 나온다. 정리하자면 결과는 변수의 값을 1을 증가한다는 면에 있어서 전위형과 후위형은 같지만 다른 연산자와 함께 쓰이면 연산 결과에 영향을 미치게 되는데 전위형의 경우 변수에 먼저 증감을 시킨 후 다른 연산을 하고 후위형의 경우 다른 연산을 한 후 마지막에 증감을 하게된다.
프로그래밍을 하다보면 조건에 따라 명령을 실행해야 하는 경우도 있는데 이때 특정한 기준, 조건에 관해 명령을 실행하려면 관계 연산자가 필요하다.
관계연산자에는 대소 관계 연산자와 동등 관계 연산자가 있다. <, >, ==(같다), !=(같지 않다)
이들 연산자는 모두 피연잔자 2개를 사용하고 연산의 결과값은 1(true) 또는 0(false) 이다.
#include <stdio.h>
int main(void)
{
int a = 10, b = 20, c = 10;
int res;
res = (a > b);
printf("a > b : %d\n", res); // a > b : 0
res = (a >= b);
printf("a >= b : %d\n", res); // a >= b : 0
res = (a < b);
printf("a < b : %d\n", res); // a < b : 1
res = (a <= b);
printf("a <= b : %d\n", res); // a <= b : 1
res = (a <= c);
printf("a <= c : %d\n", res); // a <= c : 1
res = (a == b);
printf("a == b : %d\n", res); // a == b : 0
res = (a != c);
printf("a != c : %d\n", res); // a != c : 0
return 0;
}
논리 연산자는 논리 관계를 판단하는 데 사용하며 &&(AND), ||(OR), !(NOT) 3가지이다.
&&는 논리곱(AND) 연산자로 2개의 피연산자가 모두 참일 때만 연산 결과가 참이 된다.
||는 논리합(OR) 연산자로 둘 중에 하나라도 참이면 참이 된다.
! 는 논리부정(NOT) 연산자로 피연산자를 하나 사용해 그 참과 거짓을 바꿀 때 사용된다.
#include <stdio.h>
int main(void)
{
int a = 30;
int res;
res = (a > 10) && (a < 20); // 좌항은 1 && 우항은 0, res = 0
printf("(a > 10) && (a < 20) : %d\n", res);
res = (a < 10) || (a > 20); // 좌항은 0 || 우항은 1, res = 1
printf("(a < 10) || (a > 20) : %d\n", res);
res = !(a >= 30); // ()안의 값은 1, 논리부정 연산자로 인해 res = 0
printf("!(a >= 30) : %d\n", res);
return 0;
}
&&과 || 숏 서킷 룰이 적용된다. 숏 서킷 룰이란 좌항만으로 &&와 || 연산 결과를 판별하는 기능.
&&는 좌항이 거짓이면 우항과 관계없이 거짓
||는 좌항이 참이면 우항과 관계없이 참
숏 서킷 룰에 따라 위의 상황이 오면 우항을 아예 실행하지 않는다.
따라서 (a < 0) && (++b > 20)과 같은 식에서 ++b 가 실행되길 기대한다면 동작하지 않을 것이다.
예를 들어 sum = a + b 연산을 생각해보자. 연산을 하려면 메모리에 있는 a, b값을 cpu의 저장 공간인 레지스터에 복사해야 한다. 이 과정을 로드라고 하며 연산 명령 이전에 먼저 수행된다. 데이터가 레지스터에 저장되면 연산장치인 ALU에 의해 덧셈 연산이 수행되고 그 결과값은 일단 레지스터에 저장된다. 이후 대입 연산을 수행하면 메모리 공간인 sum에 복사되어 수식의 모든 과정이 완료된다. 이 과정을 스토어라고 한다.
cpu의 메모리를 레지스터라고 하며, 여기에 연산할 데이터와 연산 후의 결과를 임시 저장한다. 보통 레지스터는 cpu의 클럭과 1:1 동기화되어 있어 메모리(RAM)에 비해 엄청나게 빠르다. 다만 레지스터는 다음 연산을 위해 계속 사용되므로 연산 결과를 메모리로 옮겨 놓지 않으면 그 값은 사라진다.
태희가 신청한 전체 학점과 평점을 계산해 신청 학점이 10학점 이상이고 평점 평균이 4.0을 넘는 경우 1을 출력하고, 그렇지 않으면 0을 출력하는 프로그램을 작성하세요. 태희가 이전 학기에 신청한 과목당 학점과 얻은 점수는 다음과 같습니다.
#include <stdio.h>
int main(void)
{
int kor = 3, eng = 5, mat = 4;
int credits;
double kscore = 3.8, escore = 4.4, mscore = 3.9;
double grade;
int res;
credits = kor + eng + mat;
grade = (kscore + escore + mscore) / 3;
res = (credits >= 10) && (grade > 4.0);
printf("%d\n", res);
return 0;
}