문장, 수식, 연산자
C 프로그램은 여러 가지 문장으로 구성되고, 대부분의 문장은 수식과 연산자로 이루어져 있다. C 프로그램을 작성하기 위해서는 이런 세 가지 내용(문장, 수식, 연산자)을 이해할 필요가 있다. 오늘은 다음과 같은 내용을 배울 것이다.
- 문장은 무엇인가?
- 수식은 무엇인가?
- C에서 사용되는 산술, 관계, 논리 연산자
- 연산자의 우선 순위
- if문
1. 문 장
: 문장(statement)은 컴퓨터에게 어떤 동작을 수행하도록 지시하는 명령문이다. C의 문장은 가끔 여러 줄에 걸쳐 나타나기도 하지만, 일반적으로 한 줄에 하나씩 입력된다. C의 문장은 #define이나 #include와 같은 선행 처리기 지시어를 제외하고는 항상 세미콜론 으로 끝난다. 앞에서는 이미 C의 여러 가지 문장을 보았었다. 예를 들어, 다음은
x = 2 + 3;
할당문(assignment statement)이다. 이것은 컴퓨터에게 2와 3을 더하여 그 결과를 변수 x에 저장하도록 지시한다. 다른 종류의 문장은 필요할 때마다 설명할 것이다.
1.1 문장과 공백
: 공백(whitespace)이라는 용어는 소스 코드에 포함되어 있는 빈칸(space), 탭(tab), 빈줄(blank line)을 일컫는 말이다. C 컴파일러는 모든 공백을 무시한다. 컴파일러는 소스 코드의 내용을 읽어들일 때 문장에 포함된 문자와 종료를 뜻하는 세미콜론을 찾지만 모든 공백을 무시한다. 그래서 다음과 같은 문장은
x=2+3;
다음과 같이 입력할 수 있다.
x = 2 + 3;
또한, 다음과 같이 사용할 수도 있다.
x =
2
+
3;
이런 특징은 소스 코드를 정리하는 데 있어서 여러 가지 융통성을 제공해준다. 그러나 앞의 예제처럼 소스 코드를 입력해서는 안된다. 하나의 문장은 변수와 연산자 주변에 몇 개의 공백을 포함시킨 상태로 한 줄에 하나씩 입력하는 것이 일반적이다. C 프로그램에 더욱 익숙해지게 되면 자신만의 기호에 맞는 문장 입력 방식을 사용하게 되는데, 중요한 것은 소스 코드를 항상 이해하기 쉽게 만들어야 한다는 것이다. 그러나 C가 공백을 무시하지 않는 예외적인 경우가 있다. 문자열 상수 내에서 사용되는 탭과 빈칸은 무시되지 않고 문자열의 일부분으로 받아들여진다. 문자열(string)은 일련의 문자들을 말한다. 실제문자열 상수(literal string constants)는 따옴표에 포함되고 컴파일러가 공백을 그대로 받아들이는 '문자열'을 말한다. 다음 예제는 비록 좋지 못한 입력 방식이지만 잘못된 것은 아니다.
printf(
"Hello, world!"
);
그러나 다음과 같은 내용은 잘못된 것이다.
printf("Hello,
world!");
실제 문자열 상수의 내용을 여러 줄로 구분하여 사용하기 위해서는 내용이 끊어지는 곳의 바로 앞에 백슬래시(\)를 포함시켜야 한다. 그래서 다음과 같은 문장은 사용할 수 있다.
printf("Hello,\
world!");
1.2 널 문장
: 만약 한 줄에서 아무런 내용도 입력하지 않고 세미콜론을 사용하면, 아무런 동작도 수행하지 않는 문장을 뜻하는 널 문장(null statement)이 된다. 이런 문장은 C에서 허용된다. 나중에 널 문장이 유용하게 사용되는 경우를 설명할 것이다.
1.3 복합문
: 블록(block)이라고도 하는 복합문(compound statement)은 괄호 내에 포함되어 있는 두 줄 이상의 C 문장들을 말한다. 다음은 블록의 예이다.
{
printf("Hello, ");
printf("world!");
}
C에서 블록은 일반적인 문장을 사용할 수 있는 곳이면 어디에서든지 사용할 수 있다. 괄호는 여러가지 방법으로 사용할 수 있다. 다음의 예는 앞에서와 같은 내용이다.
{printf("Hello, ");
printf("world!");}
블록의 시작과 끝을 분명하게 하기 위해서 괄호를 대응하는 열(column)에 위치시키는 것은 좋은 생각이다. 또한 괄호를 정렬하여 입력하게 되면 빠뜨리지 않고 입력하는데 도움이 된다.
2. 수 식
: 수식(expression)은 C에서 숫자값을 계산하거나 어떤 결과로 평가되는 것을 말한다. C의 수식은 다양한 형태로 구성될 수 있다.
2.1 단순 수식
: C의 가장 간단한 수식은 하나의 항목으로 구성된다. 이런 수식에는 간단한 변수, 실제 상수, 기호 상수등이 있다. 다음은 단순 수식의 예이다.
수 식 | 설 명 |
PI | 프로그램 내에서 정의되는 기호 상수 |
20 | 실제 상수 |
rate | 변수 |
-1.25 | 실제 상수 |
연산자의 이름 | 부 호 | 동작 내용 | 예 제 |
증가 연산자 | ++ | 연산항을 1 증가 | ++x, x++ |
감소 연산자 | -- | 연산항을 1 감소 | --x, x-- |
#include <stdio.h> int a, b; main() { a = b =5; printf("\n%d %d", a--, --b); printf("\n%d %d", a--, --b); printf("\n%d %d", a--, --b); printf("\n%d %d", a--, --b); printf("\n%d %d", a--, --b); printf("\n%d %d\n", a--, --b); return 0; } |
연산자의 이름 | 기호 | 동작 내용 | 예 제 |
덧셈 연산자 | + | 두 개의 연산항을 더한다. | x + y |
뺄셈 연산자 | - | 첫 번째 연산항에서 두 번째 연산항을 뺀다. | x - y |
곱셈 연산자 | * | 두 개의 연산항을 곱한다. | x * y |
나눗셈 연산자 | / | 첫 번째 연산항을 두 번째 연산항으로 나눈다. | x / y |
나머지 연산자 | % | 첫 번째 연산항을 두 번째 연산항으로 나눌 때 생성되는 나머지 값을 구한다. | x % y |
#include <stdio.h> #define SECS_PER_NIM 60 #define SECS_PER_HOUR 3600 unsigned seconds, minutes, hours, secs_left, mins_left; main() { printf("Enter number of seconds (< 65000): "); scanf("%d", &seconds); hours = seconds / SECS_PER_HOUR; minutes = seconds / SECS_PER_MIN; mins_left = minutes % SECS_PER_MIN; secs_left = seconds % SECS_PER_MIN; printf("%u seconds is equal to ", seconds); printf("%u h, %u m, and %u s\n", hours, mins_left, secs_left); return 0; } |
연산자 | 상대적인 우선 순위 |
++ -- | 1 |
* / % | 2 |
+ - | 3 |
<표 4.3>을 통해서 어떤 수식에서든지 연산자는 다음과 같은 순서로 사용된다는 것을 알 수 있을 것이다.
- 단항 증가 연산자와 감소 연산자
- 곱셈, 나눗셈, 나머지 연산자
- 덧셈, 뺄셈 연산자
만약 수식 내에 동일한 우선 순위를 가지는 하나 이상의 연산자가 포함되어 있다면, 수식 내의 왼쪽에서부터 오른쪽으로 진행하며 사용된다. 예를 들어, 다음과 같은 수식에서 %와 *는 동일한 우선 순위를 가지고 있지만, %는 가장 왼쪽의 연산자이므로 먼저 사용된다.
12 % 5 * 2
이 수식은 12 % 5가 2이고 2에 2를 곱한 것이 4이므로 4로 계산된다. 앞에서 사용된 예제로 돌아가서 이제 x = 4 + 5 * 3;에서는 곱셈이 덧셈보다 먼저 수행되므로, x에는 19의값이 저장된다는 것을 알 수 있을 것이다. 그렇다면, 우선 순위에 의해서 원하는 결과를 구할 수 없다면 어떤 문제가 발생할까? 앞에서 사용된 예제의 경우, 만약 4아 5를 더하고 나서 다시 3을 곱하기 원했다면 어떻게 해야 할까? C에서는 연산자의 우선 순위를 변경하기 위해서 괄호를 사용한다. 괄호 내에 포함된 수식은 연산자의 우선 순위에 관계없이 가장 먼저 계산된다. 그래서 앞의 예제는 다음과 같이 변경할 수 있을 것이다.
x = (4 + 5) * 3;
괄호 내의 수식 4 + 5가 먼저 계산되므로 x에는 27의 값이 저장될 것이다. 또한, 수식에서는 여러 개의 종속된 괄호를 사용할 수 있다. 종속된 괄호를 사용할 때에는 가장 안쪽에 있는 수식부터 바깥쪽으로 진행하며 연산이 수행된다. 다음의 복합 수식을 살펴보자.
x = 25 - (2 * (10 + 4))
이것은 다음과 같은 순서로 진행된다.
① 가장 안쪽의 수식인 8 / 2가 4의 값으로 계산되며 가장 먼저 수행된다.
② 바깥쪽으로 한 단계 이동하여 10 + 4의 수식이 14의 값으로 계산된다.
③ 마지막으로, 가장 바깥쪽의 수식인 2 * 14는 28의 값으로 계산된다.
④ 이제 남은 수식이 계산되어 -3의 값이 변수 x에 저장된다.
수식의 내용을 분명하게 하기 위해서는 원하는 곳에서 괄호를 사용할 수 있다. 이것은 우선 순위를 변경할 필요가 없는 곳에서도 가능하다. 괄호는 항상 쌍을 이루어 사용해야 하고, 그렇지 않으면 컴파일러에서 에러가 발생할 것이다.
3.4 수식의 계산 순서
: 앞에서도 설명했듯이, C의 수식에서 동일한 우선 순위를 가지는 하나 이상의 연산자를 사용할 때에는 수식의 왼쪽에서 오른쪽으로 진행하며 계산하게 된다. 예를 들어, 다음 수식에서는
w * x / y * z
w와 x를 곱한 후에 다시 y로 나누고, 마지막으로 나눗셈의 결과와 z를 곱한다. 그러나 우선 순위가 다른 연산자의 겨우에는 왼쪽에서 오른쪽으로 진행하지 않는다. 다음과 같은 수식을 살펴보자.
w * x / y + z / y
여기에서는 우선 순위에 위해서 곱셈과 나눗셈이 덧셈보다 먼저 수행된다. 그러나 w * x / z가 z / y보다 먼저 수행되는지 또는 나중에 수행되는지를 지정하지는 않으므로, 이것을 정확히 알 수는 없다. 다른 하나의 예제를 살펴보자.
w * x / ++y + z / y
만약 앞의 수식(w * x / ++y)이 먼저 계산된다면, y의 값은 뒤의 수식(z / y)이 계산될 때 증가될 것이다. 뒤의 수식이 먼저 평가된다면 y는 증가되지 않을 것이며 결가는 달라지게 된다. 그래서 프로그램을 작성할 때에는 이런 애매한 수식을 사용하지 않도록 주의해야 한다.
* 이장의 마지막 부분에서 C의 모든 연산자의 우선 순위를 참조하기 바란다.
3.5 관계 연산자
: C의 관계 연산자(relational operators)는 'x가 100보다 큰가' 또는 'y가 0과 동일한가'와 같은 내용을 질문하는 수식에서 값을 '비교하는' 경우에 사용된다. 관계 연산자가 사용되는 수식은 참(1)이나 거짓(0)으로 평가된다. <표 4.4>에는 C의 6가지 관계 연산자가 나타나 있다.
<표 4.4> C의 관계 연산자
연산자의 이름 | 기호 | 의 미 | 예 제 |
같다. | == | 연산항 x가 연산항 y와 같다. | x == y |
크다. | > | 연산항 x가 연산항 y보다 크다. | x > y |
작다. | < | 연산항 x가 연산항 y보다 작다. | x < y |
크거나 같다. | >= | 연산항 x가 연산항 y와 같거나 크다. | x >= y |
작거나 같다. | <= | 연산항 x가 연산항 y와 같거나 작다. | x <= y |
같지 않다. | != | 연산항 x가 연산항 y와 다르다. | x != y |
수 식 | 의 미 | 결 과 |
5 == 1 | 5가 1과 같다. | 0(거 짓) |
5 > 1 | 5가 1보다 크다. | 1(참) |
5 != 1 | 5가 1과 같지 않다. | 1(참) |
(5 + 10) == (3 * 5) | (5 + 10)이 (3 * 5)와 같다. | 1(참) |
{
printf("\nInput an integer value for x: ");
scanf("%d", &x);
printf("\nInput an integer value for y: ");
scanf("%d", &y);
if ( x == y )
printf("x is equal to y\n");
if ( x > y )
printf("x is greater than y\n");
if ( x < y )
printf9"x is smaller than y\n");
return 0;
}
-> 입력 / 출력
Input an integer value for x: 100
Input an integer value for y: 10
x is greater than y
4.1 else절
: if문은 선택적으로 else절을 포함할 수 있다. else절은 다음과 같은 형식을 가진다.
if (expression)
statement1;
else
statement2;
만약 expressin이 참이라면 statement1이 실행된다. expression이 거짓이라면 statement2가 실행된다. statement1과 statement2는 복합문이나 블록이 될 수 있다. <리스트 4.4>는 if문에서 else절을 사용하여 <리스트 4.3>에 있는 프로그램을 다시 작성한 것이다.
<리스트 4.4> else절을 사용하는 if문의 예
#include <stdio.h> int x, y; main() { printf("\nInput an integer value for x: "); scanf("%d", &x); printf("\nInput an integer value for y: "); scanf("%d", &y); if ( x == y ) printf("x is equal to y\n"); else if ( x > y ) printf("x is greater than y\n"); else printf("x is smaller than y\n"); return 0; } |
-> 입력 / 출력
Input an integer value for x: 99
Input an integer value for y: 8
x is greater than y
5. 관계 수식의 계산
: 관계 연산자를 사용하는 수식은 제한된 값을 가지게 되는 C의 수식이다. 관계 연산자는 수식을 거짓(0)이나 참(1)의 값으로 평가한다. 물론 관계 연산자는 if문이나 다른 어떤 조건문 내에서 가장 많이 사용되지만, 순수한 숫자값에 대해서 사용될 수도 있다. <리스트 4.5>에 있는 프로그램은 이런 사실을 설명해준다.
<리스트 4.5> 관계 수식의 사용 예를 보여주는 프로그램
#include <stdio.h> int a; main() { a = (5 == 5); printf("\na = (5 == 5)\na = %d", a); a = (5 != 5); printf("\na = ( 5 != 5)\na = %d", a); a = (12 == 12) + (5 != 1); printf("\na = (12 == 12) + (5 != 1)\na = %d\n", a); return 0; } |
-> 출 력
a = (5 == 5)
a = 1
a = (5 != 5)
a = 0
a = (12 == 12) + (5 != 1)
a = 2
5.1 관계 연산자의 우선 순위
: 앞에서 설명되었던 산술 연산자와 마찬가지로 관계 연산자는 여러 개의 연산자를 사용하는 수식에서 수행 순서를 결정하는 우선 순위를 가지고 있다. 또한 관계 연산자를 사용하는 수식에서는 우선 순위를 변경하기 위해서 괄호를 사용할 수 있다. 우선, 모든 관계 연산자는 산술 연산자보다 낮은 우선 순위를 가진다. 그래서 다음과 같은 문장을 작성한다면 x에 2를 더하고 나서 그 결과를 y와 비교하게 된다.
if (x + 2 > y)
이 문장은 우선 순위를 분명하게 해주기 위해서 괄호를 사용하는 다음 문장과 동일하다.
if ((x + 2) > y)
C 컴파일러에 의해서 요구되는 것은 아니지만, (x + 2)에서 사용되는 괄호는 전체적인 결과가 y와 비교되어야 한다는 것을 분명히 알려줄 것이다. 관계 연산자에는 두 가지 단계의 우선 순위가 있다. <표 4.6>에는 우선 순위가 나타나 있다.
<표 4.6> C의 관계 연산자의 우선 순위
연산자 | 상대적인 우선순위 |
< <= > >= | 1 |
!= == | 2 |
만약 다음과 같은 내용을 사용한다면
x == y > z
C는 0이니 1의 값으로 평가되는 y > z라는 수식을 먼저 사용하므로 다음과 같은 뜻이 될 것이다.
x == (y > z)
그리고 나서 C는 x가 처음에 계산된 1이나 0과 동일한지 비교해본다. 이러한 형태의 비교는 드물게 사용되지만 알아둘 필요가 있을 것이다.
6. 논리 연산자
: 프로그램을 작성하다 보면 가끔 하나 이상의 질문을 동시에 요구해야 하는 경우가 있다. 예를 들어, '평일이고, 오존 7시이며, 휴일이 아니라면 알람을 울린다.'와 같은 내용이 필요할 수 있다. C의 논리연산자(logical operators)는 두 개 이상의 관계 수식을 참이나 거짓으로 평가하기 위해서 하나의 수식으로 결합하는 데 사용된다. C의 세 가지 논리 연산자는 <표 4.7>에 나타나 있다.
<표 4.7> C의 논리 연산자
연산자 | 기호 | 예제 |
AND | && | exp 1 && exp2 |
OR | || | exp 1 || exp2 |
NOT | ! | !exp1 |
수 식 | 결 과 |
(exp1 && exp2) | exp1과 exp2가 모두 참이라면 참(1)이 되고, 그렇지 않다면 거짓(0)이 된다. |
(exp1 || exp2) | exp1이나 exp2의 하나가 참이라면 참(1)이 되고, 두 가지 모두 거짓인 경우에만 거짓(0)이 된다. |
(!exp1) | exp1이 참이라면 거짓(0)이 되고, exp1이 거짓이라면 참(1)이 된다. |
연산항의 참이나 거짓 값에 따라서 결과가 참이나 거짓으로 평가되는 수식에서 논리 연산자가 사용되는 것을 쉽게 볼 수 있을 것이다. <표 4.9>에는 이런 수식의 예가 나타나 있다.
<표 4.9> C의 논리 연산자의 사용 예
수 식 | 결 과 |
(5 == 5) && (6 != 2) | 두 연산항이 참이므로 참(1)이 된다. |
(5 > 1) || (6 < 1) | 하나의 연산항이 참이므로 참(1)이 된다. |
(2 == 1) && (5 == 5) | 하나의 연산항이 거짓이므로 거짓(0)이 된다. |
!(5 == 4) | 연산항이 거짓이므로 참(1)이 된다. |
또한, 여러 개의 논리 연산자를 사용하는 수식을 구성할 수도 있을 것이다. 예를 들어, 'x가 2, 3, 4 중의 하나와 동일한가?'라는 질문을 수식으로 나타내기 위해서는 다음과 같은 내용을 작성할 수 있을 것이다.
(x == 2) || (x == 3) || (x == 4)
논리 연산자는 이러한 질문에 대해서 가끔 여러 가지 해결 방법을 제공해주기도 한다. 그래서 x가 정수형 변수라면 앞의 질문을 다음과 같이 작성할 수도 있을 것이다.
(x > 1) && (x < 5)
(x >= 2) && (x <= 4)
6.1 참과 거짓을 뜻하는 값
: C의 관계 수식에서는 거짓을 나타내기 위해서 0이 사용되고, 참을 나타내기 위해서 1이 사용된다는 것을 설명했다. 그러나 참이나 거짓의 논리 값으로 평가되는 C의 수식이나 문장에서 어떤 숫자값이 사용될 때에는 숫자값 역시 참이나 거짓으로 간주된다는 사실을 기억할 필요가 있다. 이것은 다음과 같은 규칙을 가진다.
- 0의 값은 거짓을 표현한다.
- 0이 아닌 다른 모든 값은 참을 표현한다.
x의 값을 출력하는 다음 예제를 살펴보자.
x = 125;
if (x)
printf("%d", x);
x가 0이 아닌 값을 가지므로 if문에서 (x)라는 수식은 참으로 평가되는 것이다. 또한, 다음과 같은 수식은 어떤 수식에서든지
(expression)
다음과 같은 뜻을 가진다.
(expression != 0)
이러한 두 개의 수식은 expression이 0이 아니라면 참으로 평가되고, expression이 0이라면 거짓으로 평가된다. 부정 연산자(!)를 사용하면 다음과 같은 수식을 사용할 수 있다.
(!expression)
이것은 다음과 같은 뜻이다.
(expression == 0)
6.2 연산자의 우선 순위
: 예상할 수 있듯이, C의 논리 연산자에도 우선 순위가 정해져 있다. 이것은 논리 연사자간의 우선 순위뿐 아니라 다른 연산자와도 관계된 것이다. ! 연산자는 단항 연산자인 ++나 --와 같은 우선 순위를 가지고 있다. 그래서 ! 는 모든 관계 연산자와 이항 산술 연산자보다도 높은 우선 순위를 가지고 있다. 반면에, &&는 || 연산자보다 높은 우선 순위를 가지고 있지만, 이런 두 가지 연산자는 모든 산술 연산자와 관계 연산자보다 낮은 우선 순위를 가진다. C의 다른 모든 연산자에서와 마찬가지로, 논리 연산자를 사용할 때에는 우선 순위를 변경하기 위해서 괄호를 사용할 수 있다. 예제를 살펴보자.
다음과 같은 세 가지 비교를 수행하는 논리 수식을 작성하기 원한다고 하자.
① a가 b보다 작은가?
② a가 c보다 작은가?
③ c가 d보다 작은가?
조건 1이나 조건 2의 하나가 참이고, 조건 3이 참인 경우에만 전체적으로 참이 되는 수식을 작성하기 원한다면 다음과 같은 내용을 작성할 수 있을 것이다.
a < b || a < c && c < d
그러나 이것은 예상했던 대로 동작하지 않을 것이다. && 연산자는 ||보다 높은 우선 순위를 가지므로 앞의 수식은 다음과 동일하다.
a < b || (a < c && c < d)
그래서 (a < b)가 참이라면 (a < c)와 (c < d)가 참인지의 여부에 관계없이 전체적인 결과는 참이 될 것이다. 그러므로 정상적인 결과를 얻기 위해서는 다음과 같이 작성해야 할 것이다.
(a < b || a < c) && c < d
이것은 ||연산자가 &&연산자보다 먼저 수행되게 한다. <리스트 4.6>에는 이러한 두 가지 형태의 수식에 의한 결과를 비교할 수 있는 프로그램이 나타나 있다. 변수는 정상적인 경우에 결과가 거짓이 되도록 설정되어 있다.
<리스트 4.6> 논리 연산자의 우선 순위
#include <stdio.h> int a = 5, b = 6, c = 5, d = 1; int x; main() { x = a < b || a < c && c < d; printf("\nWithout parentheses the expression evaluates as %d.", x); x = (a < b || a < c) && c < d; printf("\nWith parentheses the expression evaluates as %d.\n", x); return 0; } |
->출 력
Without parentheses the expression evaluates as 1
With parentheses the expression evaluates as 0
6.3 복합 할당 연산자
: C의 복합 할당 연산자(compound assignment operators)는 할당문과 이항 산술 연산자의 기능을 동시에 사용하게 해주는 간편한 방법을 제공해준다. 예를 들어, x의 갓을 5 증가 시키거나 x에 5를 더하여 x에 저장하기 원한다고 하자. 다음과 같은 수식을 작성할 수 있을 것이다.
x = x + 5;
이것은 더욱 간편한 방법인 복합 할당 연산자를 사용하여 다음과 같이 작성할 수 있다.
x += 5;
일반적으로 복합 할당 연산자는 다음과 같은 형식을 사용한다. op는 이항 연산자를 뜻하는 것이다.
exp1 op = exp2;
이것은 다음과 같은 뜻을 가지고 있다.
exp1 = exp1 op exp2;
복합 할당 연산자에서는 이 장의 앞 부분에서 설명했던 5가지의 이항 연산자를 사용할 수 있다. <표 4.10>에는 몇 가지 예제가 설명된다.
<표 4.10> 복합 할당 연산자의 사용 예
다음과 같이 작성할 때 | 다음과 같은 의미를 갖는다. |
x *= y | x = x * y |
y -= z + 1 | y = y - z + 1 |
a /= b | a = a / b |
x += y / 8 | x = x + y / 8 |
y %= 3 | y = y % 3 |
복합 연산자는 특히 할당 연산자의 왼쪽 부분에 있는 변수가 복잡할 때 간편하고 유용하게 사용된다. 다른 모든 할당문에서와 마찬가지로 복합 할당문은 수식이므로 그 결과는 왼쪽의 변수에 저장된다. 그래서 다음의 수식을 실행하면 x와 z는 모두 14의 값을 가지게 된다.
x = 12;
z = x += 2;
6.4 조건 연산자
: 조건 연산자(conditional operator)는 세 개의 연산항을 사용하므로 3항 연산자 (ternary operator)라고 하며, C에서 제공되는 유일한 3항 연산자이다. 조건 연산자는 다음과 같은 형식으로 사용된다.
exp1 ? exp2 : exp3
exp1이 참, 즉 0이 아닌 어떤 값을 가진다면 전체적인 수식의 결과는 exp2의 값이 된다. 그러나 exp1이 0의값을 가지는 거짓으로 평가되면 전체적인 수식은 exp3의 값이 된다. 예를 들어, 다음 문장에서 y가 참이면 1의 값을 x에 할당하고, y가 거짓이면 x에 100을 할당한다.
x = y ? 1 : 100;
비슷하게, z에 x와 y 중에서 더 큰 값을 저장하기 위해서는 다음과 같은 문장을 작성할 수 있을 것이다.
z = (x > y) ? x : y;
아마도 조건 연산자가 if문과 약간 비슷한 기능을 제공한다는 사실을 알 수 있을 것이다. 그래서 앞의 예제는 다음과 같은 형태로 변경할 수 있다.
if (x > y)
z = x;
else
z = y;
조건 연산자가 모든 경우에 if....else 구조를 대신해서 사용될 수 있는 것은 아니지만 if문보다 편한 것은 사실이다. 또한, 조건 연산자는 printf()함수의 내부와 같이 if문을 사용할 수 없는 곳에서도 사용할 수 있다.
printf("The larger value is %d", ((x > y) ? x : y));
6.5 쉼표 연산자
: 쉼표(comma)는 C에서 변수의 선언, 함수의 인수 등을 독립적으로 구분하기 위한 간단한 구두점으로 자주 사용된다. 그러나 어떤 경우에는 쉼표가 내용을 구분하는 구두점이 아니라 연산자로 사용되기도 한다. 쉼표는 수식을 두 개의 부분으로 구분하기 위해서 사용될 수 있다. 이것은 다음과 같은 결과를 나타낸다.
- 수식 내에서 구분되는 두 개의 부분은 왼쪽에서 오른쪽으로 진행하며 사용된다.
- 전체적인 수식의 결과는 오른쪽에 있는 내용에 의해서 결정된다.
예를 들어, 다음 문장은 x에 b의 값을 할당하고 나서 a를 증가시키고 b를 증가시킨다.
x = (a++, b++);
++연산자가 후행 모드로 사용되기 때문에 b의 값은 증가되기 전에 x에 저장된다. 괄호는 쉼표 연산자가 할당 연산자보다도 낮은 우선 순위를 가지고 있으므로 사용된 것이다. 다음에 설명하겠지만, 쉼표 연산자가 가장 흔히 사용되는 경우는 for문에서이다.
7. 연산자 우선 순위
: <표 4.11>은 우선 순위가 감소하는 순서대로 C의 모든 연산자를 나열하고 있다. 같은 줄에 있는 연산자는 같은 우선 순위를 가진다.
단 계 | 연 산 자 |
1 | () [] -> . |
2 | ! ~ ++ -- * (간접연산자) & (주소 연산자) sizeof(형 변환) + (단항연산자) - (단항연산자) |
3 | *(곱셈 연산자) / % |
4 | + - |
5 | << >> |
6 | < <= > >= |
7 | == != |
8 | & (비트 AND 연산자) |
9 | ^ |
10 | | |
11 | && |
12 | || |
13 | ? : |
14 | = += -= *= /= %= &= ^= |= <<= >>= |
15 | , |
()는 함수 연산자이다. []는 배열 연산자이다. |
'C 언어' 카테고리의 다른 글
2장 C 프로그램의 구성 요소 (0) | 2019.06.02 |
---|---|
3장 데이터 저장하기 : 변수와 상수 (0) | 2019.06.02 |
5장 함수의 기본 (0) | 2019.06.02 |
6장 기본적인 프로그램 제어문 (0) | 2019.06.02 |
7장 입출력의 기초 (0) | 2019.06.02 |