이번엔 계산을 하기 위한 연산자를 알아볼 것이다.
연산자 : 프로그래밍 언어에서 일반적으로 연산의 집합을 의미한다.
프로그래밍에서 사용되는 연산자의 종류는 다음과 같다.
- 대입 연산자 : =
- 산술 연산자 : + , - , * , / , %
- 논리 연산자 : ! , && , ||
- 증감 연산자 : ++ , --
- 삼항연산자 : ? :
- 비트 연산자 : ! , ~ , & , ^ , >> , <<
먼저 우선순위 가장 먼저 처리되는 순서를 대충이라도 확인하고 넘어가자
| 기호 | 연산 유형 | associativity |
| [ ] ( ) . ->++--(후위) | 식 | 왼쪽에서 오른쪽 |
| sizeof & * + - ~ !++--(전위) | 단항 | 오른쪽에서 왼쪽 |
| 형식 캐스팅 | 단항 | 오른쪽에서 왼쪽 |
| * / % | 곱하기 | 왼쪽에서 오른쪽 |
| + - | 더하기 | 왼쪽에서 오른쪽 |
| << >> | 비트 시프트 | 왼쪽에서 오른쪽 |
| < > <= >= | 관계 | 왼쪽에서 오른쪽 |
| == != | 같음 | 왼쪽에서 오른쪽 |
| & | 비트 AND | 왼쪽에서 오른쪽 |
| ^ | 비트 제외 OR | 왼쪽에서 오른쪽 |
| | | 비트 포함 OR | 왼쪽에서 오른쪽 |
| && | 논리 AND | 왼쪽에서 오른쪽 |
| || | 논리 OR | 왼쪽에서 오른쪽 |
| ? : | 조건식 | 오른쪽에서 왼쪽 |
| = *= /= %=+= -= <<= >>= &=^= |= | 단순 및 복합 할당 2 | 오른쪽에서 왼쪽 |
| , | 순차적 계산 | 왼쪽에서 오른쪽 |
지금은 굳이 외울 필요 없으니 대충 보고 패스!
대입 연산자
간단하게 생각해서 뭐뭐 = 뭐뭐 다. 할 때 쓰는 = 이다.
=는 int a = 1; 이런 식으로 보통 왼쪽 변수에 오른쪽의 값을 할당할 때 사용한다.
이것은 우리가 이미 써봤으니 여기까지 설명하기로 하겠다.
(****추가****)
= , == 는 다르다
= : 할당
== : 두 값을 비교 참 또는 거짓 ( a == b )
산술 연산자
이것 또한 간단하게 생각해야지 쉬운데
말 그대로 더하기 빼기 곱하기 나누기다.
하나의 코드에 전부 활용해 보자
#include <stdio.h>
int main() {
int a = 20, b = 3;
printf("%d + %d = %d\n", a, b, a + b);
printf("%d - %d = %d\n", a, b, a - b);
printf("%d * %d = %d\n", a, b, a * b);
printf("%d / %d = %d\n", a, b, a / b);
printf("%d %% %d = %d\n", a, b, a % b);
return 0;
}
출력결과는 다음과 같을 것이다.
20 + 3 = 23 (20 에서 3을 더한 결과)
20 - 3 = 17 (20 에서 3을 뺀 결과)
20 * 3 = 60 (20 에서 3을 곱한 결과)
20 / 3 = 6 (20 에서 3을 나눈 결과)
20 % 3 = 2 (20 에서 3을 나눌 때 나머지 값!)
(****추가****)
#include <stdio.h>
int main() {
int a = 2;
if (a % 2 == 0) // a % 2 로 나눈 나머지 값이 0 인 경우
printf("짝수"); // 짝
else
printf("홀수"); // 그렇지 않다면 홀 수
return 0;
}
나머지 연산자(%)를 이용하여 간단한 홀 짝 코드를 만들 수 있다.
if는 추후 설명
관계 연산자
참과 거짓을 판단한다.
쉽게 말해서 이 부분이 논리적으로 진실인지 거짓인지 판단하는 것이다.
저번에도 말했던 것처럼 컴퓨터는 참과 거짓을 숫자 0(False) 1(True)로 표기하니 알아두도록 하자
- >, < : 크다 혹은 작다.
- == : 같다.
- != : 다르다.
- >=, <= : 크거나 같다, 작거나 같다.
#include <stdio.h>
int main() {
int a = 5, b = 5, c = 3;
printf("----0은 거짓 1은 참----\n");
printf("A와 B는 같다 : %d\n", a == b); // 두 값이 같으므로 참
printf("A와 C는 다르다 : %d\n", a != c); // 두 값이 다르므로 참
printf("C는 A보다 크다 : %d\n", a <= c); // C는 A보다 작은 값이니 거짓
printf("A는 C보다 크다 : %d\n", a >= c); // A는 C보다 크니 참
}

논리 연산자
이것도 참 혹은 거짓을 판단하는 연산자이다. 집합에 대한 결과를 연산한다.
판단과 출력은 관계연산자를 생각하면 편하다.
- ! : NOT 연산 True를 False로 False를 True로 출력한다.
- && : AND 연산 두 값이 모두 참일 때 참을 출력한다.
- || : OR 연산 두 값 중 하나라도 참이라면 참을 출력한다.
NOT 연산
| INPUT | OUTPUT |
| 1 | 0 |
| 0 | 1 |
AND 연산
| INPUT | INPUT | OUTPUT |
| 1 | 1 | 1 |
| 1 | 0 | 0 |
| 0 | 1 | 0 |
| 0 | 0 | 0 |
OR 연산
| INPUT | INPUT | OUTPUT |
| 1 | 1 | 1 |
| 1 | 0 | 1 |
| 0 | 1 | 1 |
| 0 | 0 | 0 |
이해가 가는가? 난 처음에 봤을 때 무슨 소린가 했다.
쉽게 얘기해서 이러한 조건이 있다.
키가 180 이상 이면서 몸무게가 80Kg 이상 인 사람을 뽑으려면 AND를 사용
키가 180 이상 이거나 몸무게가 80Kg 이상 인 사람을 뽑으려면 OR를 사용
#include <stdio.h>
int main() {
int A_height = 180;
int A_weight = 75;
int B_height = 184;
int B_weight = 91;
printf("키가 180이상 이면서 몸무게가 80Kg 이상 : %d\n", (A_height >= 180) && (A_weight >= 80));
printf("키가 180이상 이거나 몸무게가 80Kg 이상 : %d\n", (A_height >= 180) || (A_weight >= 80));
printf("키가 180이상 이면서 몸무게가 80Kg 이상 : %d\n", (B_height >= 180) && (B_weight >= 80));
printf("키가 180이상 이거나 몸무게가 80Kg 이상 : %d\n", (B_height >= 180) || (B_weight >= 80));
// 프로그래밍도 수학 처럼 괄호로 묶은 연산이 먼저 연산된다.
}

만들면 다음과 같이 될 것이다.
근데 여기서 NOT연산자를 쓰면?
#include <stdio.h>
int main() {
int A_height = 180;
int A_weight = 75;
int B_height = 184;
int B_weight = 91;
printf("키가 180이상 이면서 몸무게가 80Kg 미만: %d\n", (A_height >= 180) && !(A_weight >= 80));
printf("키가 180미만 이거나 몸무게가 80Kg 이상 : %d\n", !(A_height >= 180) || (A_weight >= 80));
printf("키가 180이상 이면서 몸무게가 80Kg 미만: %d\n", (B_height >= 180) && !(B_weight >= 80));
printf("키가 180미만 이거나 몸무게가 80Kg 이상 : %d\n", !(B_height >= 180) || (B_weight >= 80));
}
이 코드는 기존 코드에 논리 연산자 '!' (부정)을 추가하여 조건을 수정한 것이다.
이제 몸무게가 80kg 미만인 경우와 키가 180cm 미만인 경우를 확인할 수 있다.

! 는 보는 것처럼 연산을 수행할 곳 앞에 삽입하면 연산결과의 부정으로 리턴된다.
근데 사실 이건 괄호만 바꾸면 되는 거라 굳이 이렇게 사용할 필요는 없다.
증감 감소
값을 증가시키거나 감소시킬 때 사용한다.
++ 는 특정한 변수에 1을 더하겠다는 뜻
--는 특정한 변수를 뺀다는 뜻
- ++(변수) : n의 값을 1 증가시킨 후에 증가된 값을 반환
- (변수)++ : n의 값을 1 증가시킨 후에 증가되기 전의 값을 반환
- --(변수) : n의 값을 1 감소시킨 후에 감소된 값을 반환
- (변수)-- : n의 값을 1 감소시킨 후에 감소되기 전의 값을 반환
++(변수) 이런 경우는 값을 바로바로 증가시키는 거라 이해하겠는데.. (변수)++는 뭘까?
증감이나 감소가 된 값을 저장만 해두고 다음 출력할 때 영향을 주는 것이다. 그럼 다음 코드를 봐보자
#include<stdio.h>
int main() {
int a = 7;
printf("%d\n", ++a);
printf("%d\n", a++);
printf("%d\n", ++a);
printf("%d\n", --a);
printf("%d\n", a--);
printf("%d\n", --a);
printf("%d\n", ++a);
return 0;
}
한 줄씩 한 줄씩 생각해 보자
이건 따로 출력결과를 첨부하지 않겠다.
생각하고 직접 코드를 쳐서 결과를 보자
삼항 연산자
한 줄로 조건문을 컷낼 수 있다. 이후 배울 IF문에 축소버전이다.
#include <stdio.h>
int main() {
int a = 1, b = 1;
printf("%s\n", (a == b) ? "True" : "Fales");
}

괄호를 이용해서 수식을 넣어주고
물음표를 넣어서 그 값이 참이라면 왼쪽값이 아니라면 오른쪽값이 리턴된다.
비트 연산자

오우 쉽게 설명하기 빡센걸~?
우선 앞서 말했듯이 컴퓨터는 2진수 0과 1로 이루어져 있다. 이런 걸 비트라고 한다.
비트 : 컴퓨터 메모리 중 가장 작은 값 1(bit)
이러한 비트를 이용한 진수 연산을 하는 것인데...
이참에 2진수 표기를 알아보자 네트워크 할 때도 쓰고 코딩할 때도 쓰고 다양하게 쓰이는 컴공에 기본이라 알아가야 좋다....
2^3 2^2 2^1 2^0
8 4 2 1
-----------------
0 0 0 0 (0)
0 0 0 1 (1)
0 0 1 0 (2)
0 0 1 1 (3)
0 1 0 0 (4)
0 1 0 1 (5)
0 1 1 0 (6)
0 1 1 1 (7)
1 0 0 0 (8)
... 이하 생략 ...
오른쪽부터 1 2 4 8 16 32 64 128 256.... 이런 식으로 2에 거듭제곱 형태로 나타난다.
그렇다는 건 숫자 6을 표현하고 싶다면 00110 이런 식으로 2와 4만 키면 된다..!
컴퓨터는 모든 숫자를 위와 같이 표기한다.
예를 들어 네트워크도 이런 식으로 표기한다.
2 진수 : 11111111 11111111 11111111 00000000
10 진수 : 255.255.255.0
보통 8비트를 4번 사용하는 32bit 시스템이 기본적이다.
비트 연산자의 종류
| 연산자 | 연산자의 기능 |
| & | 비트단위로 AND 연산을 한다. |
| | | 비트단위로 OR 연산을 한다. |
| ^ | 비트단위로 XOR 연산을 한다. |
| ~ | 단항 연산자로서 피연자의 모든 비트를 반전시킨다. |
| << | 피연산자의 비트 열을 왼쪽으로 이동시킨다. |
| >> | 피연산자의 비트 열을 오른쪽으로 이동시킨다. |
& 연산자
| INPUT | OUTPUT |
| 0 & 0 | 0 |
| 0 & 1 | 0 |
| 1 & 0 | 0 |
| 1 & 1 | 1 |
| 연산자
| INPUT | OUTPUT |
| 0 | 0 | 0 |
| 0 | 1 | 1 |
| 1 | 0 | 1 |
| 1 | 1 | 1 |
^ 연산자
두 비트가 서로 다를 때 결과가 1이 되고, 그렇지 않으면 결과가 0이 된다.
| INPUT | OUTPUT |
| 0 ^ 0 | 0 |
| 0 ^ 1 | 1 |
| 1 ^ 0 | 1 |
| 1 ^ 1 | 0 |
~ 연산자
NOT(!) 생각하면 쉬움
부호를 다 바꿔버림 0은 1로 1은 0으로
| INPUT | OUTPUT |
| ~ 0 | 1 |
| ~ 1 | 0 |
<< 연산자
비트를 왼쪽으로 이동시킴
15 : 00000000 00000000 00000000 00001111
30 : 00000000 00000000 00000000 00011110
60 : 00000000 00000000 00000000 00111100
120 : 00000000 00000000 00000000 01111000
비트를 한번 왼쪽으로 이동하면 두 배가 된다.
>> 연산자
비트를 오른쪽으로 이동시킴
15 : 00000000 00000000 00000000 00001111
7 : 00000000 00000000 00000000 00000111
3 : 00000000 00000000 00000000 00000011
1 : 00000000 00000000 00000000 00000001
비트를 한번 오른쪽으로 이동하면 값이 절감된다.
다음과 같이 비트를 한 번 오른쪽으로 이동하면 값이 절반이 되고, 두 번 이동하면 1/4이 되며, 세 번 이동하면 1/8이 된다.
이제 코드를 봐볼까?
#include <stdio.h>
int main() {
int a = 12; // 이진수로 1100
int b = 25; // 이진수로 11001
int result_and = a & b; // 1100 & 11001 = 01000 (8)
int result_or = a | b; // 1100 | 11001 = 11101 (29)
int result_xor = a ^ b; // 1100 ^ 11001 = 10101 (21)
int result_not = ~a; // ~1100 = 11111111111111111111111111110011 (-13, 32비트 시스템 기준)
int result_left_shift = a << 2; // 1100 << 2 = 110000 (48)
int result_right_shift = b >> 2; // 11001 >> 2 = 00110 (6)
printf("AND 연산 결과: %d\n", result_and);
printf("OR 연산 결과: %d\n", result_or);
printf("XOR 연산 결과: %d\n", result_xor);
printf("NOT 연산 결과: %d\n", result_not);
printf("왼쪽 시프트 연산 결과: %d\n", result_left_shift);
printf("오른쪽 시프트 연산 결과: %d\n", result_right_shift);
return 0;
}

비트를 왼쪽 오른쪽 비교 그냥 지지고 돌돌 볶아서 힘들 수 있지만
앞서 설명한 32비트 2진수 체계와 연산자를 이해했다면 이해가 가능할 것이다.
(****추가****)
이경우 부호가 있는 정수인 산술 시프트인데 부호가 없는 정수인 경우 논리 시프트도 있다.
#include <stdio.h>
#include <stdint.h>
int main() {
int32_t num = -8; // 부호 있는 32비트 정수
uint32_t unum = -8; // 부호 없는 32비트 정수
int32_t arithmetic_shift = num >> 1;
uint32_t logical_shift = unum >> 1;
printf("산술 오른쪽 시프트: %d\n", arithmetic_shift);
printf("논리 오른쪽 시프트: %d\n", logical_shift);
return 0;
}

논리 시프트 설명
https://ko.wikipedia.org/wiki/%EB%85%BC%EB%A6%AC_%EC%8B%9C%ED%94%84%ED%8A%B8
이건 그냥 훑어보기만 하자
어쩌다 보니 연산자를 설명하며 이진수 체계까지 설명하게 되었다..
나름대로 쉽게 설명하려고 노력한 건데 잘 전해졌는지 모르겠다.. 나의 마음..
비트 연산자만 조금 신경 써서 공부하면 괜찮을 것이다.
다음은 드디어 "입력" 이란 것을 해보자.
'쉽게 쓰여진 C' 카테고리의 다른 글
| [C언어 3강] 서식 지정자, 세미콜론, 주석, 중괄호, 들여쓰기 (0) | 2023.04.17 |
|---|---|
| [C언어 2-1강] 변수와 데이터 타입 (심화) (0) | 2023.04.10 |
| [C언어 2-0강] 변수와 데이터 타입 (기초) (2) | 2023.04.09 |
| [C언어 1강] printf (0) | 2023.04.07 |
| C언어 세팅 Visual Studio 2022 (0) | 2023.04.07 |