C언어(학점아님)/c언어 개념

3-2. 그 외의 연산자

오버헤드프레스 2023. 3. 18. 18:23

3-1에서 논리 연산자들을 알아봤다.

3-2에서는 그 외의 연산자들을 알아보겠다.

 

형 변환 연산자

 

형 변환 연산자는 피연산자가 1개이며 피연산자의 값을 원하는 형태로 바꾼다.

예를 들어 정수 -> 실수, 실수 -> 정수.

형 변환 연산자는 일시적으로 피연산자의 값을 원하는 형태로 바꾼다.

따라서 연산 후 메모리에 있는 피연산자의 형태나 값은 변하지 않는다.

 

int a = 10; 이라고 선언하면 a는 정수형이며 그 안의 값은 정수형이다.

이 값을 일시적으로 실수로 사용하고 싶으면 a 앞에 괄호로 (double)처럼 원하는 자료형을 넣으면 된다.

 

(자료형) 피연산자 처럼 말이다.

 

(double)10  ->  10.0  //double을 사용해 실수로 바꿈
(int)10.0  ->  10     //int를 사용해 정수로 바꿈

예제를 통해 자세히 알아보자.

 

#include <stdio.h>

int main(void)
{
	int a = 20, b =3;
	double res;
	
	res = ((double)a) / ((double)b);   //(double)을 사용해 a와 b의 값을 실수로 변환
	printf("a = %d, b = %d\n", a, b);
	printf("a / b의 결과 : %.1lf\n", res);
	
	a = (int)res;      //(int)를 사용해 res의 값에서 정수 부분만 추림
	printf("(int) %.1lf의 결과 : %d\n", res, a); 
	 
	return 0;
}

a를 b로 나누면 20/3이기에 정수의 나누기이기에 결과는 6이다. 그러나 double을 붙여 형 변환 연산을 구현해

6.7의 결괏값이 나왔다. 

처음부터 a와 b를 double형으로 선언하면 편하겠지마, double형은 저장 공간이 크고 연산속도가 느리며

무엇보다 오차가 발생하므로 int형을 기본적으로 사용하는 것이 좋다.

 

 

자동 형 변환

 

컴퓨터는 데이터의 형태에 따라 다른 연산 방법을 사용하므로 피연산자가 2개 이상이라면 피연산자의 형태는 같아야 한다.

컴파일러는 컴파일 과정에서 피연산자의 형태가 다르다면 형태를 일치시키는 작업을 수행해야하는데, 이를 자동 형 변환 이라고 한다.

 

sizeof 연산자

sizeof 연산자는 피연산자를 하나만 사용할 수 있으며 피연산자의 크기를 바이트 단위로 계산해서 알려준다.

피연산자의 대상은 변수, 상수, 수식, 자료형 등이 된다.

sizeof(int)  //int형의 크기를 구할 때
sizeof(10)   //상수의 크기를 구할 때

예제를 통해 알아보자.

 

#include <stdio.h>

int main(void)
{
	int a = 10;
	double b = 3.4;
	
	printf("자료형 변수의 크기 : %d\n", sizeof(a));
	printf("double형 변수의 크기 : %d\n", sizeof(b));
	printf("정수형 상수의 크기 : %d\n", sizeof(10));
	printf("수식의 결괏값의 크기 : %d\n", sizeof(1.5 + 3.4));
	printf("char 자료형의 크기 : %d\n", sizeof(char));
	 
	return 0;
}

결과를 보니 int형 변수는 4byte이다. 1byte는 8bit이므로 int형 변수는 메모리에 32bit의 데이터를 저장할 수 있다.

상수 10은 크기가 4byte지만, 4byte로 표현할 수 없는 범위의 상수를 사용하면 8byte가 되기도 한다.

 

sizeof연산자는 sizeof('A')처럼 문자열의 크기를 확인하는 데도 사용할 수 있다.

이때 문자열 끝에는 \0이 삽입되므로 값은 2가 된다. 

 

sizeof 연산자와 괄호

sizeof는 연산자이므로 기본적으로 피연산자에 괄호를 사용할 필요가 없다.

printf("수식의 결괏값의 크기 : %d\n", sizeof 1.5 + 3.4);

그러나 이 경우 1.5만 두고 계산해서 8을 계산한 다음 3.4를 더해서 11.4가 된다.

printf("수식의 결괏값의 크기 : %d\n", sizeof char);

또한 이 경우도 char형 변수 선언문으로 인식되어 에러가 발생한다.

 

 

복합대입 연산자

복합대입 연산자는 연산 결과를 다시 피연산자에 저장한다.

산술 복합대입 연산자로는 

+=, -=, *=, /=, %= 이렇게 5가지가 있다. 예제를 통해 연산 방법을 알아보자.

 

#include <stdio.h>

int main(void)
{
	int a = 10, b = 20;
	int res = 2;
	
	a += 20;            //a와 20을 더한 결과를 다시 a에 저장 (+=) 
	res *= b + 10;      //b에 10을 더한 결괏값에 res를 곱하고 다시 res에 저장(*=)
	
	printf("a = %d, b = %d\n", a, b);
	printf("res = %d\n", res);
	 
	return 0;
}

복합대입 연산자는 대입 연산자의 특징을 그대로 가져간다.

1. 왼쪽 피연산자는 반드시 변수가 와야 한다.

2. 오른쪽 항의 계산이 모두 끝난 다음에 복합대입 연산자는 가장 마지막에 계산한다.

 

res *= b + 10; 의 계산 과정을 하나씩 살펴보자.

b + 10이 먼저 계산된다. b가 20이기에 b + 10은 30이다.

다음은 res * 30을 계산하는데 res = 2이기에 2 * 30은 60.

따라서 res = 60이라는 결괏값이 나온다.

 

 

콤마 연산자

,는 대입 연산자보다 우선순위가 낮아 여러 개의 수식을 차례로 나열해야 할 때에 사용한다.

 

조건 연산자

조건 연산자는 유일한 삼항 연산자로 ?와 : 기호를 함께 사용한다.

조건 연산자는 첫 번째 피연산자가 참이면 두 번째 피연산자가 결괏값이 되고

첫 번째 피연산자가 거짓이면 세 번째 피연산자가 결괏값이 된다.

 

첫 번째 피연산자에는 주로 조건식이 사용되며 사용 방벅은 다음과 같다.

(a > b) ? a : b  //첫 번째 조건식이 참이면 a 선택, 조건식이 거짓이면 b 선택

예제로 자세히 알아보자.

 

#include <stdio.h>

int main(void)
{
	int a = 10, b = 20, res;
	
	res = (a > b) ? a : b;     //a 와 b 중에 큰 값이 res에 저장 
	printf("큰 값 : %d\n", res); 
	 
	return 0;
}

우선 (a > b)를 수행한다. a는 10이고 b는 20이므로 > 연산의 결과는 거짓을 뜻하는 0이 된다.

거짓이기 때문에 결괏값은 세 번째 피연산자인 b값, 즉 20이 된다.

 

 

비트 연산자

비트 연산자는 비트열로 알아보도록 하자.

 

비트별 논리곱 연산자

00000000 00000000 00000000 00001010  (a = 10)
00000000 00000000 00000000 00001100  (b = 12)
------------------------------------
00000000 00000000 00000000 00001000  (a & b = 8)

논리곱 연산은 &로 표현한다. &연산은 두 비트가 모두 1인 경우에만 1로 계산한다.

 

 

비트별 배타적 논리합 연산자

00000000 00000000 00000000 00001010  (a = 10)
00000000 00000000 00000000 00001100  (b = 12)
------------------------------------
00000000 00000000 00000000 00000110  (a ^ b = 6)

배타적 논리합은 ^로 표현하며 두 피연산자의 진리값이 서로 다를 때만 참이 된다.

즉, 둘 다 참이거나 둘 다 거짓이면 거짓이고, 하나는 참이고 다른 하나가 거짓인 경우에 참이 된다.

 

 

비트별 논리합 연산자

00000000 00000000 00000000 00001010  (a = 10)
00000000 00000000 00000000 00001100  (b = 12)
------------------------------------
00000000 00000000 00000000 00001110  (a | b = 14)

논리합은 |로 표현하며 두 비트 중에 하나라도 참이면 1로 계산한다.

 

 

비트별 부정 연산자

00000000 00000000 00000000 00001010  (a = 10)
------------------------------------
11111111 11111111 11111111 11110101  (~a = -11)

비트별 부정 연산자는 ~로 표현하며 피연산자가 하나이다. 피연산자의 비트를 반전시킨다.

 

 

비트 이동 연산자

a << 1은 a의 비트들을 모두 왼쪽으로 한 비트씩 이동시킨다. 이때 왼쪽으로 밀려나는 비트는 사라지고 오른쪽의 남는 비트는 0으로 채워진다.

a >> 1은 반대이다.

 

연산자 우선순위는 3-1에서 올렸기에 또 올리지는 않는다.