C의 비트 연산

Bitwise operations in C

C 프로그래밍 언어에서는 비트 연산자를 사용하여 비트 레벨에서 연산을 수행할 수 있다.

비트 와이즈 연산은 비트 와이즈 연산자의 논리 상대인 AND, OR 연산자가 아닌 연산자를 특징짓는 바이트 레벨 연산에 의해 대조된다. 바이트 레벨 연산자는 개별 비트로 수행하지 않고 한 번에 8비트(바이트로 알려져 있음)의 문자열에서 수행된다. 그 이유는 바이트가 일반적으로 주소 지정 가능한 메모리의 가장 작은 단위(즉, 고유한 메모리 주소를 가진 데이터)이기 때문이다.

이는 비트 연산자에게도 적용되며, 이는 한 번에 1비트만 작동하더라도 바이트보다 작은 것은 입력으로 받아들일 수 없다는 것을 의미한다.

이들 연산자는 모두 C++, 그리고 많은 C-family 언어로도 이용 가능하다.

비트 연산자

C는 비트 조작을 위한 6개연산자를 제공한다.[1]

기호 연산자
& 비트 와이즈 AND
비트 포함 OR
^ 비트 XOR(전용 OR)
<< 좌교대
>> 우경화
~ Bitwise NOT(하나의 보완) (단일)

비트 와이즈 AND &

물다 비트 b a & b (A AND b)
0 0 0
0 1 0
1 0 0
1 1 1

비트 와이즈 AND 연산자는 단일 앰퍼샌드: &그것은 단지 피연산자의 진리 값보다는 피연산자의 비트에 작용하는 AND의 표현일 뿐이다. 비트 와이즈 이진 AND는 이진 형태로 숫자의 각 위치에 있는 비트의 논리적 결합(위 표에 표시)을 수행한다.

예를 들어, 바이트로 작업(문자 유형):

     11001000      & 10111000       --------     = 10001000 

첫 번째 숫자의 가장 중요한 비트는 1이고, 두 번째 숫자의 그것 또한 1이므로 결과의 가장 중요한 비트는 1이다. 두 번째 가장 중요한 비트에서는 두 번째 숫자의 비트는 0이기 때문에 우리는 0으로 결과를 얻었다.

비트 와이즈 OR

물다 비트 b a b (a OR b)
0 0 0
0 1 1
1 0 1
1 1 1

비트 와이즈 AND와 마찬가지로 비트 와이즈 OR은 비트 레벨에서 논리적 분리를 수행한다. 두 비트가 모두 0일 때만 비트 중 하나가 1이고 0이면 결과는 1이다. 그것의 상징은 파이프로 불릴 수 있다.

      11001000         10111000        --------      = 11111000 

[2]

비트 와이즈 XOR ^

물다 비트 b a ^ b (XOR b)
0 0 0
0 1 1
1 0 1
1 1 0

비트 와이즈 XOR(전용 또는)는 2비트를 추가하고 캐리어를 폐기하는 것과 동등한 배타적 분리를 수행한다. 결과는 0이 두 개 또는 두 개 있을 때만 0이 된다.[3] XOR를 사용하여 비트를 1과 0으로 전환할 수 있다. 그러므로, i = i ^ 1 루프에 사용되는 경우 값을 1과 0으로 전환하십시오.[4]

      11001000       ^ 10111000        --------      = 01110000 

시프트 연산자

두 개의 현명한 교대조 운영자가 있다. 그들은 그렇다.

  • 우측 시프트(>>)
  • 좌측 시프트(좌측 시프트)<<)

우측 시프트 >>

우측 시프트 연산자의 기호는 >>가동을 위해서는 2명의 피연산자가 필요하다. 그것은 왼쪽 피연산자의 각 비트를 오른쪽으로 이동시킨다. 연산자를 따르는 숫자는 비트가 이동되는 장소(즉, 오른쪽 연산자)의 수를 결정한다. 따라서 ch >> 3 모든 비트는 오른쪽으로 세 군데 정도 이동될 것이다.

단, 음수이거나 이 값의 총 비트 수보다 크거나 같은 시프트 피연산자 값은 정의되지 않은 동작을 유발한다는 점에 유의하십시오. 예를 들어 32비트의 부호 없는 정수를 이동할 때 32비트 이상의 이동량은 정의되지 않는다.

예:

변수인 경우 ch 비트 패턴 포함 11100101그때 ch >> 1 결과가 나올 것이다. 01110010그리고 ch >> 2 생산될 것이다 00111001.

여기서 비트가 오른쪽으로 이동하면 왼쪽에 동시에 빈 공간이 생성된다. 서명되지 않은 유형이나 서명된 유형의 음수가 아닌 값에 대해 수행할 경우 수행된 작업은 논리적인 이동으로 인해 빈 칸이 채워지게 된다. 0s (0) 서명된 유형의 음수 값에 대해 수행하면 결과는 기술적으로 구현 정의되지만(컴파일러 종속)[5] 대부분의 컴파일러는 산술적 시프트를 수행하여 빈칸을 왼쪽 피연산자의 설정 사인 비트로 채운다.

우측 시프트를 사용하여 다음과 같이 비트 패턴을 2로 나눌 수 있다.

i = 14; // 비트 패턴 00001110 j = i >> 1; // 여기서 비트 패턴이 1로 변경되어 00000111 = 7이 14/2로 변경됨 

우측 시프트 연산자 사용

C에서 우시프트 연산자의 일반적인 용도는 다음 코드에서 확인할 수 있다.

예:

#include <stdio.h>      공허하게 하다 쇼비트( 서명이 없는 인트로 x ) {     인트로 i=0;     을 위해 (i = (의 크기(인트로) * 8) - 1; i >= 0; i--)     {        설탕을 넣다(x & (1u << i) ? '1' : '0');     }     활자화하다("\n"); }  인트로 본래의( 공허하게 하다 ) {     인트로 j = 5225;     활자화하다("%d(이진수) \t\t ", j);     /* 주어진 경우 이진 문자열을 인쇄하는 함수가 있다고 가정함         소수 정수      */     쇼비트(j);      /* 우측 시프트 작동을 위한 루프 */     을 위해 (인트로 m = 0; m <= 5; m++)     {         인트로 n = j >> m;         활자화하다("%d 우측 변속 %d이(가) 제공하는 ", j, m);         쇼비트(n);     }     돌아오다 0; } 

위 프로그램의 출력은 다음과 같다.

5225 in binary           00000000000000000001010001101001 5225 right shift 0 gives 00000000000000000001010001101001 5225 right shift 1 gives 00000000000000000000101000110100 5225 right shift 2 gives 00000000000000000000010100011010 5225 right shift 3 gives 00000000000000000000001010001101 5225 right shift 4 gives 00000000000000000000000101000110 5225 우측 시프트 5로 0000000000000000000000000000000010100011 제공 

좌교대 <<

좌측 시프트 연산자의 기호는 <<. 왼쪽 피연산자의 각 비트를 오른쪽 피연산자가 표시한 위치 수로 왼쪽으로 이동시킨다. 그것은 오른쪽 교대 근무자의 그것과 반대방향으로 작동한다. 따라서 ch << 1 위의 예에서 우리는 다음과 같다. 11001010. 생성된 빈 공간은 위와 같이 0으로 채워진다.

단, 음수이거나 이 값의 총 비트 수보다 크거나 같은 시프트 피연산자 값은 정의되지 않은 동작을 유발한다는 점에 유의하십시오. 이는 ISO 9899:2011 6.5.7 비트-와이즈 시프트 운영자의 표준에 정의되어 있다.예를 들어 32비트의 부호 없는 정수를 이동할 때 32비트 이상의 이동량은 정의되지 않는다.

왼쪽 시프트는 정수를 다음과 같이 2의 힘으로 곱하는 데 사용할 수 있다.

인트로 i = 7;    // 10진수 7은 이진수(2^2) + (2^1) + (2^0) = 0000 0111 인트로 j = 3;    // 소수점 3은 이진수(2^1) + (2^0) = 0000 0011 k = (i << j); // 좌측 시프트 연산은 값을 2 곱하여 소수점 j의 힘을 얻음               // i의 이진 표현에 0을 추가하는 것과 동등               // 56 = 7 * 2^3               // 0011 1000 = 0000 0111 << 0000 0011 

예: 간단한 추가 프로그램

다음 프로그램은 AND, XOR 및 왼쪽 시프트(<)를 사용하여 두 개의 피연산자를 추가한다.

#include <stdio.h>  인트로 본래의( 공허하게 하다 ) {     서명이 없는 인트로 x = 3, y = 1, 합계를 내다, 나르다;     합계를 내다 = x ^ y; // XOR y     나르다 = x & y; // x AND y     하는 동안에 (나르다 != 0)     {         나르다 = 나르다 << 1; // 캐리어를 좌측으로 이동         x = 합계를 내다; // x를 합으로 초기화         y = 나르다; // 운반선으로 y 초기화         합계를 내다 = x ^ y; // 합계를 계산한다.         나르다 = x & y; /* 운반이 계산되고 루프 조건이                            평가된 후 프로세스가 다음 기간까지 반복됨                            운반은 0과 같다.                         */     }     활자화하다("%u"\n", 합계를 내다); // 프로그램이 4를 인쇄함     돌아오다 0; } 

비트 할당 연산자

C는 각 이진 산술과 비트 연산마다 복합 할당 연산자를 제공한다. 각 연산자는 왼쪽 피연산자와 오른쪽 피연산자를 받아들이고, 양쪽 모두에 대해 적절한 이항연산을 수행하고, 그 결과를 왼쪽 피연산자에 저장한다.[6]

비트 할당 연산자는 다음과 같다.

기호 연산자
&= 비트 AND 할당
= 비트 포함 OR 할당
^= 비트 배타적 OR 할당
<<= 좌교대 배정
>>= 오른쪽 교대 근무 할당

논리 등가물

비트 와이즈 연산자 중 4개는 등가 논리 연산자를 가지고 있다. 그들은 같은 진리표를 가지고 있다는 점에서 동등하다. 그러나 논리 연산자는 피연산자의 각 비트를 독립된 값으로 취급하기보다는 각 피연산자를 참 또는 거짓 중 하나의 값만 갖는 것으로 취급한다. 논리 연산자는 0이 거짓이고 0이 아닌 값이 참이라고 생각한다. 또 다른 차이점은 논리 연산자가 단락 평가를 한다는 것이다.

아래 표는 등가 연산자와 일치하며 a와 b를 연산자의 연산자로 나타낸다.

비트 와이즈 논리적인
a & b a && b
a b a b
a ^ b a != b
~a !a

!= 와 같은 진리표를 가지고 있다. ^ 하지만 진정한 논리 연산자와는 달리, 그 자체로 != 논리 연산자를 엄격히 말하는 것은 아니다. 논리 연산자는 0이 아닌 값을 동일하게 취급해야 하기 때문이다. 논리 연산자로 사용됨 != 먼저 피연산자를 정규화해야 한다. 두 피연산자에게 적용되지 않은 논리는 결과의 진실 테이블을 변경하지 않지만 비교 전에 모든 0이 아닌 값이 동일한 값으로 변환되도록 보장한다. 이 일은 ! 0에서는 항상 1이 되고 ! 0이 아닌 값은 항상 0이 된다.

예:

/* 등가 비트 및 논리적 연산자 검정 */ #include <stdio.h>  공허하게 하다 테스터 오퍼레이터(마를 뜨다* 이름을 붙이다, 서명이 없는 마를 뜨다 있었다, 서명이 없는 마를 뜨다 예상한);  인트로 본래의( 공허하게 하다 ) {    // -- 비트 연산자 - //     //비트로 포장된 진실 표    경시하다 서명이 없는 마를 뜨다 피연산자1    = 0x0A; //0000 1010    경시하다 서명이 없는 마를 뜨다 피연산자2    = 0x0C; //0000 1100    경시하다 서명이 없는 마를 뜨다 예상한그리고 = 0x08; //0000 1000    경시하다 서명이 없는 마를 뜨다 기대되거나  = 0x0E; //0000 1110    경시하다 서명이 없는 마를 뜨다 기대Xor = 0x06; //0000 0110      경시하다 서명이 없는 마를 뜨다 피연산자3    = 0x01; //0000 0001    경시하다 서명이 없는 마를 뜨다 예상 안 함 = 0xFE; //1111 1110     테스터 오퍼레이터("비트 AND", 피연산자1 & 피연산자2, 예상한그리고);    테스터 오퍼레이터("비트 OR", 피연산자1   피연산자2, 기대되거나);    테스터 오퍼레이터("비트 XOR", 피연산자1 ^ 피연산자2, 기대Xor);    테스터 오퍼레이터("비트와이즈 NOT", ~피연산자3, 예상 안 함);     활자화하다("\n");     // -- 논리 연산자 - //     경시하다 서명이 없는 마를 뜨다 F = 0x00; //제로    경시하다 서명이 없는 마를 뜨다 T = 0x01; //0이 아닌 값     // 배열로 포장된 진실 표     경시하다 서명이 없는 마를 뜨다 피연산자 배열1[4]    = {T, F, T, F};    경시하다 서명이 없는 마를 뜨다 피연산자 배열2[4]    = {T, T, F, F};    경시하다 서명이 없는 마를 뜨다 예상어레이앤드[4] = {T, F, F, F};    경시하다 서명이 없는 마를 뜨다 예상 ArrayOr[4]  = {T, T, T, F};    경시하다 서명이 없는 마를 뜨다 예상 ArrayXor[4] = {F, T, T, F};      경시하다 서명이 없는 마를 뜨다 피연산자 배열3[2]    = {F, T};    경시하다 서명이 없는 마를 뜨다 예상어레이Not[2] = {T, F};     인트로 i;    을 위해 (i = 0; i < 4; i++)    {       테스터 오퍼레이터("논리적 AND", 피연산자 배열1[i] && 피연산자 배열2[i], 예상어레이앤드[i]);    }    활자화하다("\n");     을 위해 (i = 0; i < 4; i++)    {       테스터 오퍼레이터("논리적 OR", 피연산자 배열1[i]    피연산자 배열2[i], 예상 ArrayOr[i]);    }    활자화하다("\n");     을 위해 (i = 0; i < 4; i++)    {       //필수! 0이 아닌 값이 다른 경우 피연산자       테스터 오퍼레이터("논리적 XOR", !피연산자 배열1[i] != !피연산자 배열2[i], 예상 ArrayXor[i]);    }    활자화하다("\n");     을 위해 (i = 0; i < 2; i++)    {       테스터 오퍼레이터("논리적 NOT", !피연산자 배열3[i], 예상어레이Not[i]);    }    활자화하다("\n");     돌아오다 0; }  공허하게 하다 테스터 오퍼레이터( 마를 뜨다* 이름을 붙이다, 서명이 없는 마를 뜨다 있었다, 서명이 없는 마를 뜨다 예상한 ) {    마를 뜨다* 결과 = (있었다 == 예상한) ? "통과" : "failed";    활자화하다("%s %s, was: %X 예상: %X \n", 이름을 붙이다, 결과, 있었다, 예상한);     } 

위 프로그램의 출력은 다음과 같다.

 Bitwise AND passed, was: 8 expected: 8  Bitwise  OR passed, was: E expected: E  Bitwise XOR passed, was: 6 expected: 6  Bitwise NOT passed, was: FE expected: FE    Logical AND passed, was: 1 expected: 1  Logical AND passed, was: 0 expected: 0  Logical AND passed, was: 0 expected: 0  Logical AND passed, was: 0 expected: 0    Logical  OR passed, was: 1 expected: 1  Logical  OR passed, was: 1 expected: 1  Logical  OR passed, was: 1 expected: 1  Logical  OR passed, was: 0 expected: 0    Logical XOR passed, was: 0 expected: 0  Logical XOR passed, was: 1 expected: 1  Logical XOR passed, was: 1 expected: 1  Logical XOR passed, was: 0 expected: 0    Logical NOT passed, was: 1 expected: 1  Logical N통과된 OT: 0 예상: 0 

참고 항목

참조

  1. ^ Kernighan; Dennis M. Ritchie (March 1988). The C Programming Language (2nd ed.). Englewood Cliffs, NJ: Prentice Hall. ISBN 0-13-110362-8. Archived from the original on 2019-07-06. Retrieved 2019-09-07. 많은 사람들에 의해 C에 대한 권위 있는 언급으로 간주된다.
  2. ^ a b "Tutorials - Bitwise Operators and Bit Manipulations in C and C++". cprogramming.com.
  3. ^ "Exclusive-OR Gate Tutorial". Basic Electronics Tutorials.
  4. ^ "C++ Notes: Bitwise Operators". fredosaurus.com.
  5. ^ "ISO/IEC 9899:2011 - Information technology -- Programming languages -- C". www.iso.org.
  6. ^ "Compound assignment operators". IBM. International Business Machines. Retrieved 29 January 2022.

외부 링크