본문 바로가기

6. 컴퓨터 공학 공부

[112] C언어 08차시 관계, 논리연산자

1. 부호연산자

가. 기능

+, - 를 변수나 상수의 앞에 사용

변수나 상수의 부호를 변경

단항 연산자(Unary Operator)

나. 사용 예

int a = -10;
int b;
b = -a;
printf("b=%d\n", b); // b=10

2. 증감연산자

가. 기능

++(증가연산자), --(감소연산자)

변수의 값을 하나 증가시키거나 감소시키는 연산자

단항 연산자

앞에 사용하면(전위) 수식의 값은 증가 / 감소된 값

뒤에 사용하면(후위) 수식의 값은 증가 / 감소되기 전(원래) 값

나. 사용 예

int a = 10;
printf("a=%d\n", a); // a=10
int b;
b = ++a;
printf("a=%d, b=%d\n", a, b); // a=11, b=11;
b = a++;
printf("a=%d, b=%d\n", a, b); // a=12, b=11;
b = --a;
printf("a=%d, b=%d\n", a, b); // a=11, b=11;
b = a--;
printf("a=%d, b=%d\n", a, b); // a=10, b=11;

3. 관계연산자

가. 종류와 기능

==(같은지), !=(다른지), >(큰지), <(작은지), >=(크거나 같은지), <=(작거나 같은지)

두 개의 피연산자를 비교하는 연산자

결과값은 참이면 1, 거짓이면 0

나. 사용 시 주의점

1) 대입연산자와 구분할 것

===는 다른 연산자

2) 관계연산자 연속으로 사용하지말 것

만약, 2 < a < 5의 경우, a가 6이면 거짓(0)이어야 하지만,

2 < a가 참(1)이고, 수식이 1 < 5가 되어 결과적으로 참(1)이 됨.

따라서 2 < a && a < 5로 사용해야 함.

3) 실수를 비교하는 경우, 약간의 오차가 발생할 수 있음.

// a가 더 크지만 같다고 판단
double a = 1e16 + 1;
double b = 1e16;
printf("%f\n", a); // 10000000000000000.000000
printf("%f\n", b); // 10000000000000000.000000
printf("a > b ?? (%d)\n", a > b); // a > b ?? (0)
printf("a == b ?? (%d)\n", a == b); // a == b ?? (1)

// 위와 1 차이지만 제대로 출력됨.
a = 1e16 + 2;
printf("%f\n", a); // 10000000000000002.000000
printf("%f\n", b); // 10000000000000000.000000
printf("a > b ?? (%d)\n", a > b); // a > b ?? (1)
printf("a == b ?? (%d)\n", a == b); // a == b ?? (0)

4. 논리연산자

가. 기능과 종류

여러 개의 조건을 조합하여 참과 거짓을 따지는 연산자

결과값은 참이면 1 ,거짓이면 0

1) AND 연산(&&)

a && b

피연산자가 모두 참이면 참, 그렇지 않으면 거짓

2) OR 연산(||)

a || b

피연산자가 모두 거짓이면 거짓, 그렇지 않으면 참

3) NOT 연산(!)

!a

피연산자가 참이면 거짓, 거짓이면 참

나. 참, 거짓의 표현 방법

!!(NOT 연산 두 번)으로 피연산자가 참인지, 거짓인지 확인 가능

0이 아닌 모든 값은 참, 0은 거짓으로 판단함.

!!0 // 0(거짓)

!!3 // 1(참)

!!-1 // 1(참)

다. 단축 계산

1) && 연산자의 경우, 왼쪽의 피연산자가 거짓이면 오른쪽의 피연산자는 계산하지 않음.

int a = 1;
printf("%d\n", a); // 1
printf("%d\n", (1 < 0) && (++a == 2)); // 0(거짓)
// &&의 왼쪽 피연산자가 거짓이므로, 오른쪽 피연산자의 ++a가 연산되지 않음.
printf("%d\n", a); // 1

2) || 연산자의 경우, 왼쪽의 피연산자가 참이면 오른쪽의 피연산자는 계산하지 않음.

int a = 1;
printf("%d\n", a); // 1
printf("%d\n", (1 > 0) || (++a == 2)); // 1(참)
// ||의 왼쪽 피연산자가 참이므로, 오른쪽 피연산자의 ++a가 연산되지 않음.
printf("%d\n", a); // 1

5. 그외 연산자

가. 조건 연산자

?:를 함께 쓰는 삼항연산자(피연산자가 3개)

? 의 왼쪽 피연산자가 참이면 : 의 왼쪽 피연산자가 출력, 거짓이면 오른쪽 피연산자가 출력

  int a = 3;
  int b = 5;
  int c;
  c = (a > b) ? a : b; // a가 더 크면 a, 그렇지 않으면 b가 할당됨.
  printf("c=%d\n", c); // c=5

나. 콤마 연산자

콤마로 연결된 수식은 순차적으로 계산

  int a = 5;
  int b = 3;
  int c, d;
  c = a + b, d = a - b; // 콤마 연산자 사용
  printf("c=%d\n", c); // c=8
  printf("d=%d\n", d); // d=2

다. 비트 연산자

& 대응되는 비트가 모두 1이면 1을 반환함. (비트 AND 연산)
| 대응되는 비트 중에서 하나라도 1이면 1을 반환함. (비트 OR 연산)
^ 대응되는 비트가 서로 다르면 1을 반환함. (비트 XOR 연산)
<< 지정한 수만큼 비트들을 전부 왼쪽으로 이동시킴. (left shift 연산)
>> 부호를 유지하면서 지정한 수만큼 비트를 전부 오른쪽으로 이동시킴. (right shift 연산)
~ 비트를 1이면 0으로, 0이면 1로 반전시킴. (비트 NOT 연산)
int a = 13; // 00001101
int b = 11; // 00001011
printf("a & b = %d\n", a & b); // a & b = 9(00001001)
printf("a | b = %d\n", a | b); // a | b = 15(00001111)
printf("a ^ b = %d\n", a ^ b); // a ^ b = 6(00000110)
printf("a >> 1 = %d\n", a >> 1); // a >> 1 = 6(0000110)
printf("a << 1 = %d\n", a << 1); // a << 1 = 26(00011010)
printf("~a = %d\n", ~a); // ~a = -14(11110010) 00001110에 대한 2의 보수