본문 바로가기
Development/C

(C언어 기초) 6. 연산자(2)

by eoieiie 2023. 8. 28.

연산자(1)에서 봤던 연산자들 말고도, 더 효율적이면서 특별한 여러 가지 연산자들이 존재합니다. 

 

형 변환 연산자


int a = 10; 이라고 선언하면 a는 정수형이고 그 안의 값은 정수입니다. 이 값을 일시적으로 실수로 사용하고 싶다면 a앞에 괄호로 (double)처럼 원하는 자료형을 넣으면 됩니다. 

 

(double)10 //10.0으로 바꾸기
(int)10.7 //10으로 바꾸기

 

예제를 통해 조금 더 자세히 살펴보겠습니다. 

 

#include <stdio.h>

int main (void)

{
    int a = 20, b =3;
    float res;

    res = ((float)a) / ((float)b); //a와 b 실수로 변환
    printf("a = %d, b = %d\n", a, b);
    printf("a / b 의 결과 : %.1f\n", res);

    a = (int)res;
    printf("(int) %.1f의 결과 : %d\n", res, a); //정수 부분만 추리고 소숫점 이하의 값은 버림. 

    return 0;
}


//실행 결과

a = 20, b = 3
a / b 의 결과 : 6.7
(int) 6.7의 결과 : 6

 

처음부터 a와 b를 double 형으로 선언해도 괜찮지만, double형은 저장 공간이 크고 연산 속도가 느리며 무엇보다 오차가 발생할 수 있으므로 int 형을  기본적으로 사용하고 실수의 연산 결과가 필요할 때만 변환하여 사용하는 편이 좋습니다. 

 

sizeof 연산자


데이터의 크기를 확인하거나 메모리를 동적으로 할당하는 작업 등에 유용하게 사용됩니다.  예제로 바로 넘어가보겠습니다. 

 

#include <stdio.h>

int main (void)

{
    int a = 10;
    float b = 3.4;

    printf("int형 변수의 크기: %d\n", sizeof(a));
    printf("float형 변수의 크기: %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형 변수의 크기: 4
float형 변수의 크기: 4
정수형 변수의 크기: 4
수식의 결괏값의 크기: 8
char 자료형의 크기: 1

 

콤마 연산자


콤마 연산자는 왼쪽부터 오른쪽으로 차례로 연산을 수행하며 가장 오른쪽의 피연산자가 최종 결괏값이 됩니다. 

 

#include <stdio.h>

int main (void)

{
    int a = 10, b = 20;
    int res;

    res = (++a, ++b); //차례대로 연산이 수행되지만, 결과적으로 res에 저장되는 값은 증가된 b의 값이다. 

    printf("a : %d, b : %d\n", a, b);
    printf("res : %d\n", res);

    return 0;
}


//실행 결과

a : 11, b : 21
res : 21

 

콤마 연산자는 대입 연산자보다 우선순위가 낮기에, 대입 연산자와 사용하기 위해서는 반드시 괄호가 필요합니다. 

res = (++a, ++b); 에서는 먼저 ++a가 수행되어 a의 값이 1증가하고, res에는 ++b의 값이 저장됩니다. 

res = ++a, ++b 에서는 먼저 res 에 ++a 가 저장되고, 그 다음에 b의 값이 +1 증가하게 됩니다. 

 

조건 연산자


조건 연산자는 유일한 삼항 연산자로 ?와 :기호를 함께 사용합니다. 첫 번째 피연산자가 참이면 두 번째 피연산자가 결괏값이 되고, 첫 번째 피연산자가 거짓이면 세 번째 피연산자가 결괏값이 됩니다. 첫 번째 피연산자에는 주로 조건식이 사용되며 사용 방법은 다음과 같습니다. 

 

(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;
}


//실행 결과

큰 값 : 20

 

이번에는 절댓값과 최솟값, 최댓값을 구하는 프로그램을 예제로 알아보겠습니다. 

 

#include <stdio.h>

int main(void)
{
    int x = -50, y = 30;
    int absoluteX = (x > 0) ? x : -x;
    int max = (x > y) ? x : y;
    int min = (x < y) ? x : y;

    printf("x의 절댓값은 %d입니다.\n", absoluteX);
    printf("x와 y중에서 최댓값은 %d입니다.\n", max);
    printf("x와 y중에서 최솟값은 %d입니다.\n", min);

    return 0;
}


//실행 결과

x의 절댓값은 50입니다.
x와 y중에서 최댓값은 30입니다.
x와 y중에서 최솟값은 -50입니다.

 

비트 연산자 


비트 연산자는 데이터를 비트 단위로 연산합니다. 비트 연산자에는 논리 연산을 수행하는  &, ||, ^, >> 같은 연산자가 있습니다. 비트 연산자는 데이터를 비트로 정확히 표현 가능한 정수에만 사용할 수 있습니다. 예제를 보겠습니다. 

 

#include <stdio.h>

int main (void)

{
    int a = 10;			// 비트열 00000000 00000000 00000000 00001010
    int b = 12;			// 비트열 00000000 00000000 00000000 00001100 

    printf("a & b : %d\n", a & b);
    printf("a ^ b : %d\n", a ^ b);
    printf("a | b : %d\n", a | b);
    printf("~a : %d\n", ~a);
    printf("a << 1 : %d\n", a << 1);
    printf("a >> 2 : %d\n", a >> 2);

    return 0;
}


//실행 결과

a & b : 8
a ^ b : 6
a | b : 14
~a : -11
a << 1 : 20
a >> 2 : 2

 

연산자들에 대한 설명은 다음과 같습니다:

 

  • 비트별 논리곱 연산자(AND, 둘 다)
printf("a & b : %d\n", a & b);

 

 & 연산은 두 비트가 모두 1인 경우에만 1로 계산합니다.

 

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

 

  • 비트별 배타적 논리합 연산자(EXCLUSIVE OR, 하나만)
printf("a ^ b : %d\n", a ^ b);

 

^ 연산은 두 비트가 서로 다른 경우만 1로 계산합니다. 

 

00000000 00000000 00000000 00001010 (a = 10)
00000000 00000000 00000000 00001100 (b = 12)
v
00000000 00000000 00000000 00000110 (a ^ b = 14)

 

  • 비트별 논리합 연산자(OR, 하나라도)
printf("a | b : %d\n", a | b);

 

| 연산은 두 비트 중에서 하나라도 참이면 1로 계산합니다. 

 

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

 

  • 비트별 부정 연산자(NOT)
printf("~a : %d\n", ~a);

 

~연산은 1은 0으로 바꾸고, 0은 1로 바꿉니다.

 

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

 

  • 비트 이동 연산자
printf("a << 1 : %d\n", a << 1);
printf("a >> 2 : %d\n", a >> 2);

 

<<연산은 비트를 왼쪽으로, >>연산은 오른쪽으로 이동시킵니다. 이 때, 밀려나는 비트는 사라지며 남는 자리의 비트는 0 또는 1로 채워지는데, 

<<연산이면 남는 자리의 비트가 0으로 채워지고, 

>>연산이면 피연산자의 부호에 따라 0 또는 1로 채워집니다. 값이 음수라면 1로, 값이 양수라면 0으로 남는 비트를 채웁니다.

 

연산자 우선순위와 연산 방향


하나의 수식에서 2개 이상의 연산자가 함께 쓰일 때는  다음과 같은 연산자 우선순위가 적용됩니다. 

  • 단항 > 이항 > 삼항 연산자 순서로 연산
  • 산술 > 비트 이동 > 관계 > 논리 연산자 순서로 연산

예제를 살펴보겠습니다. 

 

#include <stdio.h>

int main (void)

{
    int a = 10, b = 5;
    int res;

    res = a / b * 2; //우선순위 같음, 왼쪽부터 차례대로 연산
    printf("res = %d\n", res);
    res = ++a * 3; // a의 값을 +1하고 3을 곱해준다.
    printf("res = %d\n", res);
    res = a > b && a != 5;
    printf("res = %d\n", res);
    res = a % 3 == 0;
    printf("res = %d\n", res);	

    return 0;
}


//실행 결과

res = 4
res = 33
res = 1
res = 0

 

산술 연산자들의 우선순위가 같으므로 왼쪽부터 순서대로 연산됩니다. 다만 대입 연산자(=)와 단항 연산자(-a)같은 경우는 연산 방행이 오른쪽에서 왼쪽으로 수행되기에, 산술 결과가 연산된 후 res에 저장됩니다. 

 

res = a / b * 2

 

++ 연산자가 단항 연산자이므로 이항 연산자인 *보다 먼저 연산됩니다.  마찬가지로 연산된 값은 res에 저장됩니다. 

 

res = ++a * 3;

 

여기서는 관계 연산자인 >, !=가 논리 연산자인 &&보다 우선순위가 높으므로 먼저 연산됩니다. 

 

res = a > b && a != 5;

 

산술 연산자인 %가 관계 연산자인 == 보다 먼저 연산됩니다. 

 

res = a % 3 == 0;

 

산술 연산자인 %가 관계 연산자인 == 보다 먼저 연산됩니다. 

 

확인 문제


short형과 long형의 자료형의 크기를 비교하여 크기가 큰 자료형이 무엇인지 출력하세요. 

더보기
#include <stdio.h>

int main (void)

{
    int res;

    res = sizeof(short) > sizeof(long); //res 의 값 저장
    printf("%s\n", (res == 1) ? "short" : "long"); // res가 1이면 short, 아니면 long

    return 0;

}


//실행 결과

long

 

야구경기장의 좌석 수가 70개고 입장객 수가 65명일 때 입장률을 출력하세요. 

더보기
#include <stdio.h>

int main (void)

{
    int seat, person;
    float rate;
    seat = 70;
    person = 65;
    rate = ((float)person / (float)seat) * 100.0;

    printf("입장률 : %.1f퍼센트\n", (float)rate);

    return 0;

}


//실행 결과

 

3.76시간은 몇 시간, 몇 분, 몇 초인지 출력하세요.

더보기
#include <stdio.h>

int main (void)

{
    int hour, min, sec;
    float time = 3.76;

    hour = (int)time; // 3추출
    time -= hour; // 0.76 추출 
    time *= 60.0;  // 추출된 0.76은 시간이므로 60을 곱해서 45.6분을 만들어준다. 
    min = (int)time; // 45추출
    time -= min; // 0.6추출
    time *= 60.0; // 0.6은 분이므로 60을 곱해서  36.0 초를 만들어준다.
    sec = (time); // sec에 저장

    printf("3.76시간은 %d시간 %d분 %d초입니다.\n", hour, min, sec);

    return 0;

}


//실행 결과

3.76시간은 3시간 45분 35초입니다.

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

댓글