(이 포스팅은 지난 5강과 이어짐)
(5) 사칙 대입 연산자
사실 이것이 정확한 명칭인지는 모르겠지만
그런데 사칙 연산 결과를 바로 대입하는 연산자이기 때문에
그냥 마음대로 이름을 붙임 ㅋ
종류는 사칙 연산자의 개수와 같으며 형태도 굉장히 직관적이다.
1. +=
2. -=
3. *=
4. /=
5. %=
사용법은 아래를 보면 바로 이해가 갈 정도로 쉽다.
int a = 10;
a += 1;//이것과
a = a + 1;//이것은 같은 표현임
//마찬가지로
a = a * 3;//이것과
a *= 3;//이것은 같은 표현임
+ (더하기) 연산을 수행한 결과를 = (대입)
* (곱하기) 연산을 수행한 결과를 = (대입)
그럼 이제 아래 코드를 실행해보면
#include <stdio.h>
int main()
{
int a = 10;
a+=1;//1을 더함, 10 + 1 = 11
a%=3;//3으로 나눈 나머지, 11 % 3 = 2
a*=2;//2를 곱함, 2 * 2 = 4
printf("a is %d\n", a);
}
이렇게 결과가 나온다.
(6) 증감 연산자
사칙 대입 연산자로 연산이 굉장히 편리해진 것을 느낄 수 있다.
그런데 여기서 코드를 더 줄이기 위해 만들어진 연산자들이 또 있는데,
바로 단순히 1을 더하거나, 1을 빼는 것만을 위한 연산자들이다.
이 역시 굉장히 기억하기 쉬운 형태로 돼있다.
1. ++
2. --
++은 해당 변수에 1을 더하는 연산자,
--은 해당 변수에 1을 빼는 연산자이다.
다만 이것은 호출되는 위치에 따라서 작동 방식이 달라지는데
이런 증감 연산자는 두 가지 방식으로 호출할 수 있다.
int x;
x = 5;
x++;//변수 뒤에 붙이기, 후위 연산자
--x;//변수 앞에 붙이기, 전위 연산자
두 가지 방식의 차이는?
간단하지만, 이러한 차이를 이용해 여러 기법들이 만들어지곤 한다.
전위 연산자는 호출되면 즉시 x에 + 1 을 하고, 증가된 값을 반환한다.
그러나 후위 연산자는 일단 x에는 아무 일도 일어나지 않고 코드를 실행하고
그 작업이 끝나면 그제서야 x에 + 1을 하게 된다. 즉, 반환되는 값은 1만큼 증가되기 전 값이다.
아래 예제를 보자.
#include <stdio.h>
int main() {
int x;
x = 5;
printf("#1 : %d\n", x++);//일단 5가 출력된다
//그러고 나서 5 + 1이 된다.
printf("#2 : %d\n", x);//따라서 여기서 출력해야 6이 나온다.
printf("#3 : %d\n", --x);//그러나 전위 연산자는
//먼저 1을 뺀다
//따라서 #3은 6 - 1 = 5가 다시 출력된다.
}
#1은 후위 연산자라 출력된 후 값이 변경됐지만
#3은 전위 연산자라 변경된 값이 출력된 걸 볼 수 있다.
다른 변수에 대입을 해본다면
이렇게 결과가 나온다.
처음에 x = 0인데, y에 대입하고 나서 x + 1을 했으므로
첫 줄에는 x : 1, y : 0 이 출력되는데
다시 y = ++x; 를 하면 먼저 x + 1이 되어 x = 2가 되고
그것이 y에 대입되어 x, y 둘다 2로 출력되는 것을 볼 수 있습니다.
(7) 비트 연산자
비트 연산자는
이름 그대로 비트를 다룰 수 있는 연산자이다.
C언어에서 가장 작은 size를 가진 자료형인 char, 이 크기가 1Byte여서 다른 언어에서는
char라는 이름 대신 byte라는 이름을 사용하기도 한다.
이 Byte가 모든 값의 기본이 되지만
이 역시 나눠보면 8Bits로 이루어져있기 때문에
그 Bit들을 잘 활용해서 효율적인 연산을 할 수 있다.
예를 들어 정수 50을 비트로 저장하면 다음과 같습니다.
00110010
이러한 비트를 가지고 여러 연산을 할 수 있는 건데
그 종류는 다음과 같다.
1. & (AND)
2. | (OR)
3. ^ (XOR)
4. >>, << (Shift)
5. ~ (NOT)
각각 AND 연산자, OR 연산자, XOR 연산자, Shift 연산자, NOT 연산자라고 불린다
ㄱ) AND 연산자부터 살펴보면
AND 연산자는 비트를 하나씩 비교해서 둘 다 1이면 1, 하나만 1이거나 둘 다 1이 아니면 0으로 반환한다.
예시를 들어서
정수 3은 바이너리 형태로 0011이고
정수 5는 바이너리 형태로 0101이다.
그림을 그려보면
(3 & 5)
↓↓↓
0011
0101
-------
0001
이 된다.
3, 5 모두 마지막 비트만 양쪽 값이 1이기 때문에
결과가 0001이 나왔다.
즉 3 & 5는 1과 같습니다.
printf("%d\n", 3 & 5);//1
ㄴ) OR 연산자는
AND와 다르게 둘 중 하나만 1이어도 결과가 1이 된다.
즉 3 | 5 는 이렇게 된다.
(3 | 5)
↓↓↓
0011
0101
-------
0111
둘 중 하나만 1일 때 1이 되는 것이 아니라, 둘 중 하나라도 1이면 1이 되기 때문에
세 비트가 1이 되었다.
따라서 printf로 출력하면 7이 출력된다.
printf("%d\n", 3 | 5); //7
ㄷ) XOR 연산자가 좀 흥미로운데
OR과 비슷하지만, 차이점은 반드시 두 비트가 달라야 한다는 것이다.
즉, 둘 중 하나만 1일 때 1이 된다.
(3 ^ 5)
↓↓↓
0011
0101
-------
0110
즉 최종 결과는 6이 된다.
printf("%d\n", 3 ^ 5) //6
ㄹ) Shift 연산자
Shift의 사전적 의미가?
이동이라고 나온다.
저 번역처럼 쉬프트 연산자는 비트를 이동시키는 기능을 한다.
쉬프트 연산자는 <<, >> 로 두 가지가 있는데
<< 는 왼쪽, >>는 오른쪽으로 이동시킨다.
예를 들어 3은 바이너리로 0011 인데
3 << 1을 하면 0011을 왼쪽으로 한 칸 이동시킨다는 의미이다.
0 | 0 | 1 | 1 |
이걸 왼쪽으로 이동시키면
0 | 1 | 1 | 0 |
이렇게 된다. (굵은 0은 자리가 이동해서 채워진 비트로, 기본적으로 << 연산자는 빈 자리를 0으로 채운다)
즉 3 << 1은 6과 같다.
그럼 반대로
3 >> 2를 하면 왼쪽으로 두 칸 이동하는데
왼쪽으로 두 칸 이동하면
0 | 0 | 0 | 0 |
이 되서 결국엔 결과가 0이 된다. 그런데 >> 연산자는 언제나 0으로 채워지는 것이 아니다.
그 이유는 다음 포스팅에서 비트 연산자에 대한 내용을 조금 더 깊게 얘기할 때 다룰 것이다.
ㅁ) ~ (NOT) 연산자
~ 은 모든 비트를 반전시켜준다. 0은 1로, 1은 0로 말이다.
~3 은 이진법으로 표기했을 때 1100과 같다.
~0 은 이진법으로 표기했을 때 1111과 같다.
~1 은 이진법으로 표기했을 때 1110과 같다.
int a = 3;
~a; // 0011 -->> 1100
ㅂ)
비트 연산자들도 사칙 대입 연산자처럼
대입 연산자와 결합될 수 있습니다.
예시는 << 와 | 만 들었지만 다른 연산자들도 원리는 똑같다.
int a = 3;
a <<= 1;//a = a << 1;과 같음
//3 << 1은 6이므로 a = 6이 됨
a = 3;//다시 a = 3
a |= 5;//3 ^ 5가 7이므로 a = 7이 됨
(8) sizeof 연산자
sizeof 연산자는 대상의 size, 크기를 얻을 수 있습니다.
sizeof 연산자는 크기를 정수형태로 표현(반환)하는데
이때 쓰이는 자료형은 size_t이다.
size_t는 별 거 없이 그저 정수형 타입이다. 예를 들어 size_t는 그저 int를 기반으로 tyepdef 된 것인데 typedef는 간단히 말해서 새로운 자료형을 정의할 때 사용된다.
size_t라는 정수형 자료형을 새로 정의한 것이다.
사용법은 이렇다.
sizeof(int);
sizeof("HelloWorld");
sizeof(30);
sizeof(3.2);
sizeof(3.2f);
첫 강좌에서 HelloWorld를 출력할 때 printf 처럼 ( ) 가 붙는 걸
함수라고 했는데 sizeof는 특이하게 함수가 아닌 연산자이다.
이렇게 자료형을 넣어줄 수도, 값들을 넣어줄 수도 있는데
자료형을 넣어준다면 해당 자료형의 크기가, 값을 넣어준다면 그 값의 자료형의 크기를 알 수 있다.
int 타입의 크기는 32bits, 즉 4Bytes라서 4가 출력됐고
30은 정수형이니 기본적을 int로 인식해 4가 출력됐고
2.5는 double형으로 인식해 8Bytes,
2.5f는 뒤에 f가 붙어 float형으로 인식해 4Bytes가 출력됐다.
다음 포스팅에서 비트 연산자 중 Shift 연산자에 대해 이어간다.
끝..
'Programming > C & C++' 카테고리의 다른 글
[C/C++] 6강 - C언어에서 형변환 하기 (형변환 연산자) (0) | 2021.06.16 |
---|---|
[C/C++] 5.2강 - 시프트 연산자가 작동하는 방법 (0) | 2021.06.12 |
[C/C++] 5강 - C의 다양한 연산자(사칙연산자,관계연산자,논리연산자) (0) | 2021.06.09 |
[C/C++] 2.1강 - 변수 이름 규칙, 변수 이름 표기법 (카멜,파스칼,스네이크) (0) | 2021.06.09 |
[C/C++] 4강 - 자료형에 대하여··· (부동 소수점, ASCII, signed & unsigned) (0) | 2021.06.06 |