[C 언어의 기초]연산자 3부






기타 연산자 - 2




4. 관계 연산자, 논리 연산자 : 연산 결과는 0(거짓) 또는 1(참)
㉠ 관계 연산자

관계 연산자는 조건 판단 등의 관계(>, <, = 등)를 판정하는 것으로 다음과 같은 종류가 있다.

연산자

기 능

우선 순위

>

크다

1

>=

크거나 같다

1

<

작다

1

<=

작거나 같다

1

==

같다

2

!=

같지 않다

2



조건 판단에서 「같다」는 ==라고 = 기호 두 개를 연속으로 쓰는 것에 주의해야 한다. 한 개의 =은 대입연산자이므로 그 의미가 완전히 다르다. 다음의 의미를 생각해 보자.

i > 0, i >= 10, i == 0, i != 0 등

/* 임의의 산술식에 관계 연산을 적용한 예제 프로그램 */

#include<stdio.h>

main()

{

char ch = 'A';

int I = 1,j = 2,k = -3;

double x = 7.23e+33,y = 0.001;

printf(" %d\n", 'C'- 15 < ch);

printf(" %d\n", -i –4 * j >= k * k);

printf(" %d\n", I < k > j);

printf(" %d\n", x - 5.555 <= x + y / 0.234);

printf(" %d\n", x < x+y);

}


㉡ 논리 연산자
논리 연산자에서는 몇 가지 조건 판단을 형성하는 것으로 &&, ||, !의 세 가지가 있다.

연산자

기능

우선순위

!

부정(NOT)

1

&&

그리고(AND)

2

¦¦

또는(OR)

3


조건식에 대해서는 뒤에서 if 문과 함께 설명하겠지만 예를 들면 a>b && b>c …a>b 이고 그리고 b>c a>b ¦¦ b>c && c==3……&&는 ¦¦ 보다 우선 순위가 먼저이기 때문에 먼저 b>c && c==30이 평가된다. 다음의 의미를 각자 생각해 보자.

(c >= 'A') && (c<= 'Z')

!((c < 'A') || (c > 'Z'))




5. bit 연산자 : <<, >>, &, |, ^, ~
① shift 연산자(<<, >>) : 비트별로 연산자 다음에 주어진 숫자만큼 이동한다.

x << y 의 의미는 x에 저장된 데이터 비트를 y만큼 좌로 이동시키는 것입니다.

x >> y 의 의미는 x에 저장된 데이터 비트를 y만큼 우로 이동시키는 것입니다.


만약 데이터의 비트가 왼쪽(오른쪽)으로 이동하게 되면, 왼쪽(오른쪽) 끝의 최상단(최하단) 비트 자리에 있는 데이터는 다음 자리에 있는 데이터가 들어오기 때문에 없어지고 오른쪽(왼쪽) 끝자리에 0이 채워집니다.

좌/우 이동 연산자(<<, >>)를 사용할 때 주의할 점은 이동 연산자의 좌측에 있는 피연산자 x는 항상 정수형이어야 하고, 우측에 있는 피연산자 y는 양의정수형이어야 합니다. 그리고 y의 정수 값은 x의 비트 크기를 넘어서는 안 됩니다.


/* 여백문자, 알파벳 대/소문자, 숫자의 수를 세는 프로그램 */

#include<stdio.h>

main()

{

char ch;

int alpa_count = 0, digit_count = 0,

white_count = 0, other_count = 0;

printf("Input number of characters : ");

while((ch = get char()) ! = EOF)

{

if(ch == '' || ch == '\n' || ch == '\t')

white_count++;

if(ch >= 'A' && ch <= 'Z' || ch >= 'a' && ch <= 'z')

alpa_count++;

if(ch >= '0' && ch <= '9')

digit_count++;

}

printf("There are %d whitespace characters.\n", white_count);

printf("There are %d alphabet characters.\n", alpa_count);

printf("There are %d digit characters.\n", digit_count);

}


② AND(&), OR(|), XOR(^), 1의 보수(~) : 비트 단위로 수행되는 연산자이다.

비트 논리 연산자는 1개의 단항 연산자와 3개의 이항 연산자가 있는데, 이들 각 연산자는 학생이 알고 있는 논리 연산자와 동일한 진리 값을 가지며, 논리 연산자와의 차이점은 논리 연산자가 피연산자로 전체 단어(word)나 바이트가 가지는 값을 그 대상으로 사용하는 반면에 비트 논리 연산자는 기억 장소의 2진 값인 각 비트를 그 대상으로 한다는 점입니다. 

비트 단위연산은 정수를 그 대상으로 하기 때문에 8진, 16진, 10진 정수를 사용해야 하지만 편의상 여러분의 이해를 돕기 위해서 16진수나 기억장소에 실제 데이터가 표현되는 2진수 표현을 사용하기로 합니다. 그러나 C 언어에서 2진수 표현은 사용할 수 없다는 것을 명심하기 바랍니다.

Ⓐ 1의 보수 연산자(~)

1의 보수 연산자는 단항 연산자로서 피연산자가 저장된 기억장소의 각 비트들을 토글(toggle)시킵니다. 즉, 0을 1로 바꾸고, 1을 0으로 바꾸어 줍니다.


(10001010) == ~ (01110101)



Ⓑ 비트 단위 AND (&) 연산자

비트 단위 AND 연산자는 이항 연산자입니다. 즉, 연산을 실행하기 위해서 2개의 비트 피연산자가 필요하며, 2개의 비트 피연산자 중 한 비트 값이라도 0이면, 결과 비트 값은 0이 됩니다. 즉, 2개의 비트 피연산자 값이 모두 1일 때 만 결과 비트 값이 1이 됩니다.

(11010101) & (01101101) == (01000101)


위에서 보는 것처럼 비트 단위 AND 연산자는 피연산자로 사용되는 2개의 비트값 이 00, 01, 10일 때에는 그 결과 값이 0이고, 11일 때에만 1이 됩니다. 비트 단위 AND 연산자는 마스크라는 특별한 동작을 실행하여 하드웨어의 특정 flag 비트를 제어할 때 사용합니다. 

마스크(mask)는 비트 패턴으로 구성된 flag 비트들 중 특정 비트영역만 선택하여 원래의 비트 패턴으로 보호하고 나머지 영역은 0으로 비트 값을 설정하는 동작을 말합니다. 예를 들면, flag라는 변수에 같이 데이터 103이 저장되어 있다고 할 때, 이들 비트 패턴 중 비트 번호 1, 2 (두 번째와 세번째 비트)인 비트만 원래의 데이터를 가지도록 할 때 나머지를 0으로 설정하는 마스크 동작을 실행하려면 다음과 같이 하면 됩니다.

mask = 6;

flag = flag & mask;

실행 과정은 각자 2진수로 표현하여 알아보기 바랍니다.


Ⓒ 비트 단위 OR (|) 연산자


비트 단위 OR 연산자는 2개의 비트 피연산자중 적어도 하나만 1이면 그 결과 비트 값이 1이 되는 연산을 실행합니다. 비트 단위 AND 연산자와 유사하게비트 간 의 OR 연산자도 컴퓨터의 하드웨어를 제어하는데 사용됩니다. 즉 비트 켜기(bit ON)라는 특별한 동작을 실행하는데, 비트 켜기는 flag 비트의 패턴들 중 지정한 비트 영역의 비트패턴의 값을 1로 설정하고, 나머지 영역의 비트 영역은 원래의 비트 패턴으로 유지하도록 하는 연산입니다.

Ⓓ 비트 단위 XOR (^) 연산자

피연산자로 사용되는 2개의 비트가 서로 다른 경우에 그 결과 비트 값이 1이 됩니다. 아래의 확인 문제 2-15처럼, 비트 단위 XOR연산을 취하면 flag 변수의 비트 패턴은 mask의 비트 패턴에 의해 토글(toggle)됩니다.

Ⓔ 비트 끄기(bit OFF)

확인 문제 17처럼, ~mask로 비트단위 AND 연산을 실행하면 마스크 영역의 비트 패턴만 0으로 설정되고 나머지 영역은 그대로 남아 있습니다. 즉, 특정영역을 0으로 설정하는 비트 끄기입니다. 이 연산자들을 잘 이해하고, 그 쓰임새를 완전히 파악하려면 확인 문제 17을 반드시 실행해서 확인하기 바랍니다.

/*비트 단위 논리 연산자(~, &, |, ^)를 이용한 마스크, 비트 켜기/끄기, 반전(toggle)의 예 */

#include<stdio.h>

main()

{

unsigned char flag, mask;

flag = 103; mask=6;

printf("flag = %#0x, flag & mask = %#0x\n", flag, flag & mask);

flag = 6; mask = 48;

printf("flag = %#0x, flag | mask = %#0x\n", flag, flag | mask);

flag = 103; mask =255;

printf("flag = %#0x, flag ^ mask = %#0x\n", flag, flag ^ mask);

flag = 103; mask = 6;

printf("flag = %#0x, flag & ~mask = %#0x\n", flag, flag & ~ mask);

}






Reactions

댓글 쓰기

0 댓글