비트와 여러 연산자
조건 연산자 (Conditional Operator)
C 언어에서 유일하게 3개의 **Operand(피연산자)**를 갖는 삼항 연산자이다. 이 연산자는 ?와 : 두 개의 기호로 구성된다.
문법: exp1 ? exp2 : exp3
exp1이 참(0이 아닌 값)으로 평가되면, 전체 연산식의 결과는exp2의 값이 된다.exp1이 거짓(0)으로 평가되면, 전체 연산식의 결과는exp3의 값이 된다.
예를 들어, max = (a > b) ? a : b; 문장은 a가 b보다 크면 max에 a를, 그렇지 않으면 b를 할당한다. 이는 if-else 문을 간결하게 표현하는 방법이다.
비트 논리 연산자 (Bitwise Logical Operators)
**Bitwise Logical Operator(비트 논리 연산자)**는 정수 값을 비트 단위로 논리 연산을 수행하는 연산자이다.
| 연산자 | 기호 | 의미 |
|---|---|---|
| AND | & | 두 피연산자의 각 비트에 대해 AND 연산을 수행한다. |
| OR | ` | ` |
| XOR | ^ | 두 피연산자의 각 비트에 대해 XOR 연산을 수행한다 (두 비트가 다를 때 1). |
| Complement | ~ | 단일 피연산자의 모든 비트를 반전시킨다 (1의 보수). |
비트 연산 진리표:
| 비트 x | 비트 y | x & y | x | y | x ^ y | ~x |
| -------- | -------- | ------- | ------- | ------- | ---- |
| 0 | 0 | 0 | 0 | 0 | `` |
| 0 | 1 | 0 | 1 | 1 | 1 |
| 1 | 0 | 0 | 1 | 1 | 0 |
| 1 | 1 | 1 | 1 | 0 | 0 |
예를 들어, 3 & 5 연산은 각 숫자의 32비트 이진수 표현에 대해 비트별 AND 연산을 수행한다. 3(00...011)과 5(00...101)를 AND 연산하면 1(00...001)이 된다.
이동 연산자 (Shift Operators)
**Shift Operator(이동 연산자)**는 변수의 비트들을 지정된 횟수만큼 왼쪽 또는 오른쪽으로 이동시킨다.
| 연산자 | 기호 | 의미 |
|---|---|---|
| 왼쪽 이동 | << | 비트를 왼쪽으로 이동시킨다. |
| 오른쪽 이동 | >> | 비트를 오른쪽으로 이동시킨다. |
- 왼쪽 이동 (
<<): 비트들을 왼쪽으로 이동시키고, 왼쪽 경계를 벗어나는 비트는 버려진다. 오른쪽의 빈자리는 모두 0으로 채워진다.a << b연산은a에2^b를 곱하는 효과와 같다. - 오른쪽 이동 (
>>): 비트들을 오른쪽으로 이동시키고, 오른쪽 경계를 벗어나는 비트는 버려진다. 왼쪽의 빈자리는 원래 숫자의 부호 비트(최상위 비트)로 채워진다. 만약 피연산자가 양수라면a >> b연산은a를2^b로 나누는 효과와 같다.
비트 마스크 (Bit Mask)
**Bit Mask(비트 마스크)**는 특정 비트들만 선택하거나 변경하기 위해 사용하는 상수나 변수이다.
- 특정 비트 값 확인: 확인하려는 비트 위치만 1이고 나머지는 0인 마스크를 만들어
&연산을 수행한다. 예를 들어, 변수a의 n번째 비트를 확인하는 일반식은(a & (1 << (n-1)))이다. - 특정 비트 값 변경:
- 비트를 1로 설정:
|연산을 사용한다. - 비트를 0으로 설정: 해당 비트만 1인 마스크를
~로 반전시킨 후&연산을 사용한다. - 비트 반전(toggle):
^연산을 사용한다.
- 비트를 1로 설정:
기타 연산자
sizeof 연산자
sizeof는 변수나 자료형이 메모리에서 차지하는 크기를 바이트 단위로 반환하는 연산자이다. sizeof(자료형) 또는 sizeof 변수명 형태로 사용하며, 자료형에는 괄호가 필수이다.
형변환 연산자 (Type Casting)
C언어는 연산 시 자료형이 다른 피연산자들을 하나의 통일된 자료형으로 자동 변환한다. 크기가 작은 형에서 큰 형으로 변환되는 것을 **Promotion(형 넓히기)**이라고 한다.
반대로, 큰 형에서 작은 형으로 변환(형 좁히기)할 때는 정보 손실이 발생할 수 있다. Type Casting(형변환) 연산자 (자료형)를 사용하여 명시적으로 자료형을 변환할 수 있다.
int x = 6, y = 4;
double result;
result = (double)x / y; // result는 1.5가 된다. x를 double로 형변환 후 나눗셈 수행.
result = x / y; // result는 1.0이 된다. 정수 나눗셈 후 결과를 double로 저장.
축약 대입 연산자 (Compound Assignment Operator)
+=, -=, *= 등은 산술/비트 연산과 대입 연산을 결합한 형태이다. 예를 들어, x += y는 x = x + y와 동일한 의미를 가진다.
콤마 연산자 (Comma Operator)
콤마 연산자는 우선순위가 가장 낮다. 왼쪽에서 오른쪽으로 연산을 수행하며, 전체 연산식의 결과값은 가장 마지막에 수행된 연산의 결과가 된다.
-
x = 3+4, 5-10;: 대입 연산자가 콤마보다 우선순위가 높아x = 7이 먼저 수행되고,5-10은 의미 없는 구문이 된다. -
x = (3+4, 5-10);: 괄호 안의 콤마 연산자가 먼저 수행된다.3+4가 수행된 후5-10이 수행되고, 마지막 결과인-5가x에 대입된다.
연산자 우선순위
C 언어의 연산자는 정해진 **Operator Precedence(연산자 우선순위)**에 따라 평가된다. 일반적으로 우선순위는 다음과 같다:
- 괄호
(), 배열[], 구조체.-> - 단항 연산자 (
++,--,!,~,sizeof) - 산술 연산자 (
*,/,%,+,-) - 이동 연산자 (
<<,>>) - 관계 연산자 (
<,>,<=,>=) - 등가 연산자 (
==,!=) - 비트 논리 연산자 (
&,^,|) - 논리 연산자 (
&&,||) - 조건 연산자 (
?:) - 대입 연산자 (
=,+=,-=, 등) - 콤마 연산자 (
,)
조건문
조건문은 특정 조건을 만족할 때만 해당하는 코드를 실행하도록 제어하는 문장이다.
if 문
**if statement(if 문)**는 주어진 표현식(expression)이 참(0이 아닌 값)일 경우에만 뒤따르는 문장(statement)을 실행한다. 여러 문장을 실행하려면 중괄호{}로 묶어야 한다.
if (grade >= 4.3) {
printf("장학금을 받습니다.\n");
}
if-else 문
else 키워드를 사용하면 if문의 표현식이 거짓일 경우 실행할 문장을 지정할 수 있다.
if (number % 2 == 0) {
printf("짝수(even) 입니다.\n");
} else {
printf("홀수(odd) 입니다.\n");
}
중첩된 if 와 else if 문
중첩된 if 문은 if문 내부에 또 다른 if문이 포함된 구조이다. 이 때 else는 자신과 가장 가까운 if와 연결되므로, 의도치 않은 동작을 피하기 위해 중괄호{}를 명확히 사용하는 것이 중요하다.
여러 조건을 순차적으로 검사할 때는 else if 구조를 사용하는 것이 더 명확하다.
if (point >= 90) {
printf("학점은 A입니다.\n");
} else if (point >= 80) {
printf("학점은 B입니다.\n");
} else {
printf("학점은 C 이하입니다.\n");
}
switch 문
switch문은 하나의 정수 표현식 값에 따라 여러 경로 중 하나를 선택하여 실행하는 다중 선택문이다. if-else if 구조보다 코드가 간결해질 수 있다.
-
switch (expression):expression은 반드시 정수형으로 평가되어야 한다. -
case value::expression의 결과값과value(정수 상수)가 일치하면 해당case의 문장부터 실행된다. -
break:switch블록을 즉시 빠져나간다.break가 없으면 일치하는case이후의 모든case문장들이 순차적으로 실행된다(fall-through). 이를 이용해 여러case에 대해 동일한 코드를 실행시킬 수 있다.
-
default: 어떤case와도 일치하지 않을 때 실행된다.
윤년 계산 예시: switch문과 if문을 활용하여 특정 년도의 월별 마지막 날을 계산할 수 있다. 2월의 경우, 윤년을 판별하는 로직이 필요하다. 윤년의 조건은 다음과 같다:
- 4로 나누어 떨어지면서 100으로 나누어 떨어지지 않는 해
- 또는 400으로 나누어 떨어지는 해
((year % 4 == 0) && (year % 100 != 0)) || (year % 400 == 0)