비트 연산자와 시프트 연산자로 비트 단위 연산하기

  • 38 minutes to read

비트 연산자(&, |, ^, ~)와 시프트 연산자(<<, >>)는 이진수 비트 단위로 연산을 수행합니다. 변수 값을 비트 단위로 연산하는 비트 연산자와 시프트 연산자의 사용법을 알아봅시다.

> // 비트 연산자: & (비트단위 AND), | (비트단위 OR), ^ (비트단위 XOR), ~ (비트단위 NOT)
> // 시프트 연산자: << (왼쪽 시프트), >> (오른쪽 시프트), >>> (부호없는 오른쪽 시프트) 

책읽기: 비트 연산자와 시프트 연산자로 비트 단위 연산하기 강의 소개

비트 연산자와 시프트 연산자의 종류

비트 연산자와 시프트 연산자는 2진수 비트 단위로 연산을 수행하는데 사용합니다. 우선 비트 연산자와 시프트 연산자의 7가지 종류를 표로 간단히 미리 살펴본 후 진행하겠습니다.

[표] 비트 연산자와 시프트 연산자의 종류

연산자 별칭 설명
& 비트단위 AND 비트 값이 둘 다 1일 때에만 1, 그렇지 않으면 0
| 비트단위 OR 비트 값이 하나라도 1이면 1, 그렇지 않으면 0
^ 비트단위 XOR 비트 값이 서로 다를 때에만 1, 그렇지 않으면 0
~ 비트단위 NOT 비트 값이 1이면 0, 0이면 1
<< 왼쪽 시프트 비트 값을 지정된 수만큼 왼쪽으로 이동
>> 오른쪽 시프트 비트 값을 지정된 수만큼 오른쪽으로 이동
>>> 부호없는 오른쪽 시프트 비트 값을 지정된 수만큼 오른쪽으로 이동하되 왼쪽을 0으로 채움

비트 연산자

비트 연산자(Bit Operator)는 정수형 데이터의 값을 이진수의 비트 단위로 연산을 수행하고자할 때 사용됩니다. 비트 연산자는 다음과 같이 4개의 기호를 사용합니다. 좀 더 구분을 짓기 위해서 영문 단어를 추가했습니다.

  • &
    • 논리곱(AND, Both)
  • |
    • 논리합(OR, Either)
  • ^
    • 배타적 논리합(XOR; Exclusive OR, Different)
  • !
    • NOT(Negation, Invert)

비트 연산자 AND, OR, XOR 간단 소개 동영상

https://youtu.be/Z19Iv9m0PLc

Windows 계산기를 사용하여 이진수 비트 연산자 4개에 대한 실행 결과 살펴보기

https://youtu.be/aYpD6cHqpsk

Windows OS에 내장된 계산기를 사용하면 표준, 공학용, 프로그래머용 등의 여러 가지 환경을 사용할 수 있습니다.

그림: 계산기

계산기

비트 AND 연산자(&) 사용하기

본격적으로 비트 연산자를 사용하도록 하겠습니다. 먼저, 비트 AND 연산자인 & 연산자를 사용해 보겠습니다. 다음 코드를 주석을 제외하고 작성 후 실행해보세요.

그림: 계산기로 AND 연산 수행하기

계산기로 AND 연산 수행하기

코드: BitAnd.cs

> // & 연산자: 비트 AND 연산자(둘 다 1일때만 1)
> byte x = 0b1010; // 10
> byte y = 0b1100; // 12
> 
> // x를 이진수로 표현 -> 십진수로 표현
> Console.WriteLine($"  {Convert.ToString(x, 2)} -> {x}");
  1010 -> 10
> 
> // y를 이진수로 표현 -> 십진수로 표현
> Console.WriteLine($"& {Convert.ToString(y, 2)} -> {y}"); 
& 1100 -> 12
> 
> // x AND y를 이진수로 표현 -> 십진수로 2칸 잡고 표현 
> Console.WriteLine($"  {Convert.ToString(x & y, 2)} -> {x & y, 2}");
  1000 ->  8

비트 AND 연산자인 & 연산자처럼 항을 2개 갖는 2항 연산자는 앞뒤로 공백을 두면 가독성이 좋아집니다. 즉, x%y 보다는 x % y 형태를 추천합니다.

비트 OR 연산자(|) 사용하기

이번에는 비트 OR 연산자인 | 연산자를 사용해 보겠습니다. | 연산자는 키보드의 파이프 기호(버티컬 바)를 사용합니다.

그림: 계산기로 OR 연산 수행하기

계산기로 OR 연산 수행하기

코드: BitOr.cs

> // | 연산자: 비트 OR 연산자(하나라도 1이면 1)
> using static System.Console; // System.Console 줄여서 사용
> 
> byte x = 0b1010; // 10
> byte y = 0b1100; // 12
> 
> // x를 이진수로 표현 -> 십진수로 표현
> WriteLine($"  {Convert.ToString(x, 2)} -> {x}");
  1010 -> 10
> 
> // y를 이진수로 표현 -> 십진수로 표현
> WriteLine($"| {Convert.ToString(y, 2)} -> {y}");
| 1100 -> 12
> 
> // x OR y를 이진수로 표현 -> 십진수로 표현 
> WriteLine($"  {Convert.ToString(x | y, 2)} -> {x | y,2}");
  1110 -> 14

나중에 프로그래머로 일을 하다 보면 이진수 처리가 중요한 분야가 있을 수 있습니다. 지금은 '이런 연산자를 사용하면 이렇게 나오는구나' 정도로 가볍게 읽고 넘어갑니다.

비트 XOR 연산자(^) 사용하기

비트 XOR 연산자 ^는 두 비트의 값이 서로 다를 때 1이 되는 연산자입니다. 즉, 1 ^ 00 ^ 1일 때만 1이고, 나머지 경우에는 0이 됩니다.

XOR은 "엑스오어"라고 읽으며, ^ 기호는 흔히 "삿갓"이라고도 하지만, 정확한 명칭은 "캐럿(caret)"입니다.

그림: 계산기로 XOR 연산 수행하기

계산기로 XOR 연산 수행하기

코드: BitXor.cs

> // ^ 연산자: 비트 XOR 연산자(서로 다르면 1)
> using static System.Console;
> 
> byte x = 0b_1010; // 10
> byte y = 0b_1100; // 12
> 
> // x를 이진수로 표현 -> 십진수로 표현
> WriteLine($"  {Convert.ToString(x, 2)} -> {x}");
  1010 -> 10
> 
> // y를 이진수로 표현 -> 십진수로 표현
> WriteLine($"^ {Convert.ToString(y, 2)} -> {y}");
^ 1100 -> 12
> 
> // x XOR y를 이진수로 표현 -> 십진수로 표현 
> WriteLine($"  {Convert.ToString(x ^ y, 2).PadLeft(4, '0')} -> {x ^ y,2}");
  0110 ->  6

^ 연산자를 포함한 몇몇 비트 및 시프트 연산자는 이번 예제 이외에는 다루지 않습니다. 그러므로 현재 예제는 가볍게 작성 후 실행해보세요.

비트 연산자는 하드웨어 제어 같은 경우가 아니면 자주 쓰이지 않습니다. 여기서는 비트 연산자의 사용법만 살펴보면 충분합니다.

비트 NOT 연산자(~) 사용하기

비트 NOT 연산자인 ~ 연산자는 물결(틸드) 기호를 사용합니다. ~ 연산자는 비트 값이 1이면 0으로 0이면 1로 바꿉니다. 이렇게 비트가 바뀌는 것이 '비트 반전'입니다.

그림: 계산기로 비트 반전

계산기로 NOT 연산 수행하기

계산기로 NOT 연산 수행하기

코드: BitNot.cs

> // ~ 연산자: 비트 NOT 연산자(1 <-> 0, 비트 반전)
> using static System.Console;
> 
> byte x = 0b_0000_1010; // 10
> 
> // x를 8자리 이진수로 표현 -> 십진수로 3자리 잡고 표현
> WriteLine($"~ {Convert.ToString(x, 2).PadLeft(8, '0')} -> {x, 3}");
~ 00001010 ->  10
> 
> // NOT x를 8자리 이진수로 표현 -> 십진수로 3자리 잡고 표현 
> WriteLine($"  {Convert.ToString((byte)~x, 2).PadLeft(8, '0')} -> {~x, 3}");
  11110101 -> -11

음수를 이진수로 표현할 때는 2의 보수법을 사용합니다. C#에서는 자동으로 이진수를 양수 또는 음수로 해석하여 출력합니다.

비트 연산자 4가지 모두 사용해보기

이번에는 비트 연산자 4개를 모아서 사용해 보겠습니다. 다음 내용을 입력한 후 실행해 보세요.

코드: BitwiseOperator.cs

// 비트 연산자: &, |, ~, ^
using System;

class BitwiseOperator
{
    static void Main()
    {
        var x = Convert.ToInt32("1010", 2); // 10
        var y = Convert.ToInt32("0110", 2); // 6

        var and = x & y;
        Console.WriteLine($"{and} : {Convert.ToString(and, 2)}"); // 2, 0010

        var or = x | y;
        Console.WriteLine($"{or} : {Convert.ToString(or, 2)}"); // 14, 1110

        var xor = x ^ y;
        Console.WriteLine($"{xor} : {Convert.ToString(xor, 2)}"); // 12, 1100

        var not = ~x; // 2의 보수법에 의해서 1010 + 1 그리고 부호를 -로 -1011 => -11
        Console.WriteLine($"{not} : {Convert.ToString(not, 2)}"); // -11, ~~~~0101
    }
}
2 : 10
14 : 1110
12 : 1100
-11 : 11111111111111111111111111110101

이진수 10100110에 대해서 &, |, ^ 연산자를 사용한 결과와 1010~연산자를 붙여 비트를 반전시키는 연산의 사용 결과가 나옵니다.

시프트 연산자

시프트 연산자(Shift Operator)는 정수 데이터가 담겨 있는 메모리의 비트를 왼쪽(<<) 또는 오른쪽(>>, >>>)으로 지정한 비트만큼 이동시켜주는 기능을 제공합니다.

시프트 연산자를 사용하면 비트의 자리를 다음과 같이 이동할 수 있습니다.

  • x << y : xy만큼 왼쪽으로 이동
  • x >> y : xy만큼 오른쪽으로 이동
  • x >>> y : xy만큼 부호없이 왼쪽을 0으로 채우며 오른쪽으로 이동

예를 들어, 정수형 데이터인 2를 이진수로 표현하면 0010입니다. 왼쪽(<<) 시프트 연산자를 사용하여 한 칸 이동하면 0100이 됩니다. 이진수 0010을 오른쪽(>>) 시프트 연산자를 사용하여 한 칸 이동하면 0001이 됩니다.

비트 연산자의 사용 예를 표로 정리하면 다음과 같습니다.

연산자 사용 예 설명
<< 변수 << 비트값; 비트값 만큼 왼쪽으로 비트 이동
결괏값이 변수의 값 * 2의 비트값 제곱 == 비트당 2배
변수의 값 곱하기 2의 거듭제곱
>> 변수 >> 비트값; 비트값 만큼 오른쪽으로 비트 이동
결괏값이 변수의 값 / 2의 비트값 제곱 == 비트당 1/2배
변수의 값 나누기 2의 거듭제곱

그림: 계산기로 2 << 2 실행하기

왼쪽 시프트

그림: 계산기로 40 >> 2 실행하기

오른쪽 시프트

시프트 연산자에 대한 내용을 그림으로 표현하면 다음과 같습니다.

그림: 시프트 연산자

시프트 연산자

시프트 연산자

정수 2의 이진수인 0010을 왼쪽으로 2칸 이동하면 1000이 되어 정수 8이 됩니다.

정수 40의 이진수인 0101000를 오른쪽으로 2칸 이동하면 0001010이 되어 정수 10이 됩니다.

시프트 연산자 사용하기

코드로 시프트 연산자를 사용해 보도록 하겠습니다.

***코드: ShiftOperatorDemo.cs ***

> int number = 2; // 0010
> 
> Console.WriteLine(number << 1); // 0010 -> 0100 : 4
4
> 
> Console.WriteLine(number >> 1); // 0010 -> 0001 : 1
1

이진수 0010을 왼쪽으로 비트를 한 칸 이동하면 0100이 되고 이진수 0010을 오른쪽으로 비트를 한 칸 이동하면 0001이 됩니다. 시프트 연산자는 내부적으로는 이진수로 계산이 되지만 정수형 데이터이기에 출력할 때에는 그대로 십진수로 표현됩니다.

부호 없는 오른쪽 시프트 연산자(>>>) 사용하기

C#에서는 오른쪽 시프트 연산자로 산술 오른쪽 시프트 연산자(>>)와 부호 없는 오른쪽 시프트 연산자(>>>)의 두 가지를 사용할 수 있습니다.

C# 11에서 도입된 >>> 연산자는 부호 없는 오른쪽 시프트 연산자로, 왼쪽 피연산자를 오른쪽 피연산자가 지정한 비트 수만큼 오른쪽으로 이동시킵니다. 이때, >>> 연산자는 왼쪽 피연산자의 유형과 관계없이 상위 비트 위치를 항상 0으로 설정합니다.

다음 코드는 음수 값을 오른쪽으로 시프트하는 부호 없는 오른쪽 시프트 연산자의 사용 예제를 보여줍니다.

코드: UnsignedRightShiftDemo.cs

using static System.Console;

class UnsignedRightShiftDemo
{
    static void Main()
    {
        int x = -4;
        WriteLine($"{x,11}, {Convert.ToString(x, 2).PadLeft(32, '0'),32}");

        int y = x >> 1;
        WriteLine($"{y,11}, {Convert.ToString(y, 2).PadLeft(32, '0'),32}");

        int z = x >>> 1;
        WriteLine($"{z,11}, {Convert.ToString(z, 2).PadLeft(32, '0'),32}");
    }
}
         -4, 11111111111111111111111111111100
         -2, 11111111111111111111111111111110
 2147483646, 01111111111111111111111111111110

위 코드에서 x의 초기값은 -4이며, 이를 이진수로 나타내면 11111111 11111111 11111111 11111100입니다. 먼저, x산술 오른쪽 시프트 연산자(>>)를 적용하면 최상위 비트(부호 비트)를 유지한 채 한 비트씩 오른쪽으로 이동합니다. 따라서 결과는 11111111 11111111 11111111 11111110이 되며, 이는 10진수로 -2에 해당합니다.

반면, x부호 없는 오른쪽 시프트 연산자(>>>)를 적용하면, 부호와 관계없이 왼쪽의 빈 비트를 항상 0으로 채우면서 한 비트씩 이동합니다. 따라서 결과는 01111111 11111111 11111111 11111110이 되며, 이는 10진수로 2147483646에 해당합니다.

이처럼 산술 오른쪽 시프트(>>)는 최상위 비트를 유지하여 음수를 그대로 유지하는 반면, 부호 없는 오른쪽 시프트(>>>)는 상위 빈 비트를 0으로 설정하기 때문에 음수 값이 양수로 변환될 수 있습니다.

비트 연산자와 시프트 연산자를 할당 연산자와 함께 사용하기

비트 연산자와 시프트 연산자도 할당 연산자와 함께 사용할 수 있습니다. 사용 방법은 일반적인 할당 연산자와 동일합니다.

  • A &= B;
  • A |= B;
  • A ^= B;
  • A <<= B;
  • A >>= B;

이번에는 할당 연산자와 함께 비트 연산자, 시프트 연산자를 사용해 보겠습니다.

코드: BitwiseAssignment.cs

> byte num1 = 4; // 4: 0000_0100
> num1 &= 5;  // 5(0101) & 4(0100) => 4(0000_0100)
> Console.WriteLine(num1); // 4
4
> 
> byte num2 = 4; // 4: 0000_0100
> num2 |= 1;  // 1(0001) & 4(0100) => 5(0000_0101)
> Console.WriteLine(num2); // 5
5
> 
> byte num3 = 4; // 4: 0000_0100
> num3 ^= 2;  // 2(0010) & 4(0100) => 6(0000_0110) 
> Console.WriteLine(num3); // 6
6
> 
> byte num4 = 4; // 4: 0000_0100
> num4 <<= 1; // 4(0100) << 1 => 8(0000_1000)
> Console.WriteLine(num4); // 8
8
> 
> byte num5 = 4; // 4: 0000_0100
> num5 >>= 1; // 4(0100) >> 1 => 2(0000_0010)
> Console.WriteLine(num5); // 2
2

결과는 2진수 비트 연산 후 그 결괏값을 다시 변수에 할당한 내용이 출력됩니다.

비트 연산자와 시프트 연산자는 C언어와 같은 프로그래밍 언어로 성능이 낮은 장치에 대한 프로그래밍할 때 많이 사용됩니다. 다만, C#에서 응용 프로그램을 제작할 때에는 자주 사용되지 않습니다. 이번 강의의 예제의 내용 정도만 이해하고 다음으로 넘어가도 충분합니다.

기타 연산자

앞에서 살펴본 연산자 외에도 여러 연산자가 있습니다. 그중 조건 연산자와 나열 연산자, sizeof 연산자를 살펴봅시다.

조건 연산자

> // 조건 연산자(3항 연산자): "조건식 ? 조건식이참일때의값 : 조건식이거짓일때의값"

물음표와 콜론 기호를 함께 사용하는 "? :" 형태의 모양을 갖는 조건 연산자(Conditional Operator)도 있습니다. 조건연산자는 조건에 따라서 참(true)일 때와 거짓(false)일 때의 결과를 다르게 반환하고자 할 때 사용됩니다. 조건 연산자는 항이 3개여서 3항 연산자(Ternary Operator)라고도 합니다. 3항 연산자는 뒤에서 다룰 if ~ else문의 축약형이기도 합니다.

> (5 > 3) ? "TRUE" : "FALSE"
"TRUE"

3항 연산자인 ?: 연산자는 항이 3개가 있는 연산자로 다음과 같이 조건을 처리합니다.

조건식 ? 식1 : 식2;

조건식이 참이면 식1이 실행되고 조건식이 거짓이면 식2가 실행됩니다.

3항 연산자의 결괏값이 특정 값을 반환하기에 다음과 같이 표현하기도 합니다.

조건식 ? 값1 : 값2;

?: 연산자 보충 설명

다음 예제와 같이, 3개로 구성된 조건 연산자라고도 하는 조건 연산자 ?:은 부울 식을 계산하고 부울 식이 true 또는 false로 계산되는지에 따라 두 식 중 하나의 결과를 반환합니다.

(tempInCelsius < 20.0) ? "Cold." : "Perfect!";

위의 예제에서 볼 수 있듯이 조건 연산자의 구문은 다음과 같습니다.

condition ? consequent : alternative

condition 식은 true 또는 false로 계산되어야 합니다. conditiontrue로 계산되면 consequent 식이 계산되고 해당 결과가 연산 결과가 됩니다. conditionfalse로 계산되면 alternative 식이 계산되고 해당 결과가 연산 결과가 됩니다. consequent 또는 alternative만 계산됩니다.

조건부 연산자는 오른쪽 결합성입니다. 즉, 다음 형식의 식을 가정해 보세요.

a ? b : c ? d : e

이 식은 다음과 같이 계산됩니다.

a ? b : (c ? d : e)
TIP

다음과 같은 니모닉 디바이스(mnemonic device)를 사용하여 조건부 연산자의 평가 방식을 기억할 수 있습니다.

is this condition true ? yes : no

조건 연산자 사용하기

3항 연산자인 조건 연산자를 사용해보겠습니다.

코드: ConditionalOperator.cs

> //[?] 3항 연산자(조건 연산자) 사용하기 
> int number = 3;
> 
> // number가 짝수면 result 변수에 "짝수" 담고 그렇지 않으면 "홀수" 담기 
> string result = (number % 2 == 0) ? "짝수" : "홀수";
> 
> Console.WriteLine($"{number}은(는) {result}입니다.");
3은(는) 홀수입니다.

num 변수에 3을 넣어 놓은 후 (num % 2 == 0)을 물어보면 거짓(false)이 됩니다. 물음표(?) 기호 앞의 식이 false이기에 '홀수'가 result 변수에 담깁니다. 즉, 조건식이 참이면 '짝수'를 반환, 그렇지 않으면 '홀수'를 반환합니다. 참고로, 조건 연산자, 즉 3항 연산자는 앞으로 배울 제어문의 if 문으로 대체할 수 있습니다.

조건 연산자를 사용하여 최댓값 정하기

이번에는 조건 연산자를 사용하여 최댓값을 우리가 원하는 값으로 정하는 방법을 알아보겠습니다.

코드: OperatorMaxSize.cs

> //[?] 들어오는 값이 20 이상이면 20으로 초기화, 20 미만이면 해당 값으로 초기화
> const int maxSize = 20; // 최댓값을 20으로 정함
> int pageSize = 0;
> 
> pageSize = 10;
> pageSize = (pageSize > maxSize) ? maxSize : pageSize; // 10
> pageSize
10
> 
> pageSize = 50;
> pageSize = (pageSize > maxSize) ? maxSize : pageSize; // 20
> pageSize
20

pageSize 변수에 들어오는 값이 20보다 작으면 pageSize 값 그대로 출력하고, 20 이상이면 20으로 고정하는 기능을 구현해 보았습니다.

조건 연산자를 사용하여 문자 비교하기

이번에는 조건 연산자를 사용하여 문자 크기를 비교해 보겠습니다.

코드: TernaryOperator.cs

> string result = "";
> 
> // 'A'는 'B'보다 작으므로 참이므로 앞에 문자열이 result 변수에 저장
> result = ('A' < 'B') ? "'A'는 'B'보다 작습니다." : "A B C 순서로 커집니다.";
> result
"'A'는 'B'보다 작습니다."
> 
> // 'Z'는 'a'보다 작으므로 참이므로 앞에 문자열이 result 변수에 저장
> result = ('Z' < 'a') ? "'Z'는 'a'보다 작습니다." : "대문자보다 소문자가 더 큽니다.";
> result
"'Z'는 'a'보다 작습니다."

프로그래밍 언어에서는 A, B, C, …, Z, a, b, c, …, z 순서로 크기가 정해져 있습니다. 이러한 크기를 조건 연산자의 조건식에 두고 크기를 비교해 보았습니다.

조건(3항) 연산자로 절댓값 구하기

조건 연산자인 3항 연산자를 사용하면 다음 코드처럼 정수의 절댓값을 편하게 구할 수 있습니다.

코드: AbsoluteValue.cs

> var num = -21; // 음수 값을 저장
> var abs = (num < 0) ? -num : num; // 3항 연산자로 음수만 부호 변환
> Console.WriteLine($"{num}의 절댓값: {abs}");
-21의 절댓값: 21

나열(콤마) 연산자

이미 변수 선언할 때 다루어 보았지만, 콤마를 구분자로 하여 하나의 문장에 여러 개의 변수 선언문을 지정할 때 사용합니다. 이러한 콤마 연산자(Comma Operator)를 나열 연산자라고도 합니다. 나열 연산자는 다음과 같이 사용됩니다.

int a = 10, b = 20, c = 30;

위와 같이 콤마로 3개의 할당문이 지정되면, a, b, c 변수 모두 int 형 변수로 선언됩니다.

IMPORTANT

콤마 연산자는 코드가 복잡해질 수 있기에 가능하면 사용하지 않습니다.

sizeof 연산자로 데이터 타입의 크기 구하기

sizeof 연산자는 단항 연산자로서 데이터 타입 자체의 크기를 구하는데 사용됩니다. sizeof(int) 형태로 사용되며 int의 데이터 타입 크기인 4가 값으로 나옵니다. 참고로, sizeof 연산자의 결괏값이 플랫폼마다 다르게 나올 수 있습니다.

코드: SizeOf.cs

> //[?] sizeof 연산자로 데이터 형식의 크기 구하기
> Console.WriteLine("sizeof(데이터 형식)");
sizeof(데이터 형식)
> Console.WriteLine($"  char 형식: {sizeof(  char)} byte");     
  char 형식: 2 byte
> Console.WriteLine($"   int 형식: {sizeof(   int)} byte");      
   int 형식: 4 byte
> Console.WriteLine($"  long 형식: {sizeof(  long)} byte");      
  long 형식: 8 byte
> Console.WriteLine($" float 형식: {sizeof( float)} byte");     
 float 형식: 4 byte
> Console.WriteLine($"double 형식: {sizeof(double)} byte");    
double 형식: 8 byte

sizeof 연산자는 다른 연산자와 달리 sizeof() 형태로 괄호로 묶어주는 형태를 가집니다. C#의 기본 제공 형식의 크기는 예를 들어 double이라면 sizeof(double) 형태로 구할 수 있습니다.

연산자 우선 순위

여러 개의 연산자를 사용할 때에는 연산자의 우선순위(Precedence)에 따라서 계산됩니다. 예를 들어 산술 연산자에서 +보다 *가 더 우선순위가 높습니다. 괄호 연산자인 ()연산자를 사용하면 우선순위를 변경할 수도 있습니다.

표: 우선순위가 적용된 산술 연산 구문

우선순위가 적용된 산술 연산 구문

다음은 C#의 주요 연산자 우선순위입니다.

표: 연산자 우선순위

연산자 우선순위

연산자 우선순위는 따로 외울 필요 없이 괄호 연산자만 잘 사용해도 무방합니다. 나머지는 자연스레 프로그래밍을 배우면서 알아 가면 됩니다.

다음 코드는 참고용으로 살펴보세요.

코드: OperatorPrecedence.cs

> 3 + 4 * 2
11
> (3 + 4) * 2
14
> 10 / 5 * 2 + 1
5
> 15 / (5 * (2 + 1))
1

장 요약

3항 연산자인 조건 연산자는 조건식이 참일 때와 거짓일 때에 따라 서로 다른 값을 받고 싶을 때 사용합니다. 이 연산자는 다음 강의에서 배울 if 문으로 대체가 가능합니다. 그 외에 콤마 연산자와 연산자 우선순위도 학습했습니다. 연산자는 이 정도로 정리하고 다음 강의부터는 제어문을 학습하겠습니다

정보처리산업기사 실기 시험 기출 문제 - 비트 및 논리 연산 출력

문제

다음 C# 프로그램이 실행되었을 때의 동작을 설명하고, 출력 결과를 예측하시오.

소스 코드 파일명: BitwiseLogicalOperations.cs

using System;

class BitwiseLogicalOperations
{
    static void Main()
    {
        int x = 1;
        Console.WriteLine(!(x > 0));
        Console.WriteLine(x > 0 || x < 4);
        Console.WriteLine(x << 2);
        Console.WriteLine(x & 2);
        Console.WriteLine(x % 3);
    }
}

입력 예시

이 프로그램은 입력을 받지 않습니다.

출력 예시

False
True
4
0
1

해설

이 프로그램은 변수 x의 값에 대한 여러 가지 비트 연산 및 논리 연산을 수행하고 그 결과를 출력합니다.

  1. int x = 1;는 정수 변수 x를 선언하고 1로 초기화합니다.
  2. Console.WriteLine(!(x > 0));x > 0의 조건이 참이므로, ! 연산자를 사용하여 그 결과를 반전시킵니다. 따라서 False가 출력됩니다.
  3. Console.WriteLine(x > 0 || x < 4);x > 0 또는 x < 4의 조건 중 하나라도 참이면 True를 반환합니다. 두 조건 모두 참이므로, True가 출력됩니다.
  4. Console.WriteLine(x << 2);x의 값을 왼쪽으로 2비트 이동시킵니다. x의 값인 1을 2진수로 01로 표현할 때, 왼쪽으로 2비트 이동시키면 100이 되어, 10진수로 4가 됩니다. 따라서 4가 출력됩니다.
  5. Console.WriteLine(x & 2);x의 값과 2를 비트 AND 연산합니다. x의 2진수 값 01과 2의 2진수 값 10을 AND 연산하면 00이 되어, 10진수로 0이 됩니다. 따라서 0이 출력됩니다.
  6. Console.WriteLine(x % 3);x를 3으로 나눈 나머지를 출력합니다. 1을 3으로 나눈 나머지는 1이므로, 1이 출력됩니다.

이 프로그램은 기본적인 비트 연산과 논리 연산을 통해 다양한 결과를 출력하며, 조건 연산자와 비트 이동 연산자 등의 사용 방법을 이해하는 데 도움을 줍니다. C#에서는 논리 연산 결과를 대문자 TrueFalse로 출력하는 것을 제외하고는 Java와 매우 유사한 동작을 합니다.

정보처리산업기사 실기 시험 기출 문제 - 복합 비트 연산 및 조건식

문제

다음 C# 프로그램이 실행되었을 때의 동작을 설명하고, 출력 결과를 예측하시오.

소스 코드 파일명: ComplexBitwiseLogicalOperations.cs

using System;

class ComplexBitwiseLogicalOperations
{
    static void Main()
    {
        int a = 5, b = 9, c;
        c = b % 5 < 5 ? 1 : 0;
        c = c | (c << 3);
        c = (a < 5 || c >= 10) ? (c - a) : (c + a);
        Console.WriteLine(c);
    }
}

입력 예시

이 프로그램은 입력을 받지 않습니다.

출력 예시

14

해설

이 프로그램은 변수 a, b, c에 대한 복합 비트 연산 및 조건식을 이용하여 최종적으로 c의 값을 결정하고 출력합니다.

  1. int a = 5, b = 9, c;는 정수 변수 a, b, c를 선언하고 초기화합니다.
  2. c는 먼저 b % 5 < 5 조건을 평가하여 1로 설정됩니다. 이는 b의 나머지가 5보다 작을 경우 1, 그렇지 않으면 0c에 할당하는 조건 연산자입니다.
  3. 그 다음, c는 자기 자신과 자기 자신을 3비트 왼쪽으로 이동한 값과의 비트 OR 연산 결과로 업데이트됩니다. 이 연산은 c9를 할당합니다.
  4. 마지막으로, (a < 5 || c >= 10) 조건을 평가한 후, 해당 조건이 거짓이므로 (c + a) 연산을 수행하여 c14가 됩니다.
  5. Console.WriteLine(c);는 수정된 c의 값인 14를 출력합니다.

이 프로그램은 복합 비트 연산과 조건식을 사용하여 변수의 값을 조작하는 과정을 보여주며, 이러한 연산들이 어떻게 결합되어 최종 결과를 도출하는지를 이해하는 데 도움을 줍니다. C#에서는 이러한 비트 및 조건 연산을 통해 복잡한 논리를 간결하게 표현할 수 있습니다.


1.1 퀴즈

(1) 4 & 1의 연산 결과로 올바른 것을 고르세요.

a. 0000 0000 (0)
b. 0000 0010 (2)
c. 0000 0100 (4)
d. 0000 0110 (6)
e. 0000 1000 (8)

정답: a

비트 AND(&) 연산자는 두 비트가 모두 1일 때만 1이 됩니다.

0100 (4)
0001 (1)
   &
0000 (0)

(2) 4 | 1의 연산 결과로 올바른 것을 고르세요.

a. 0000 0001 (1)
b. 0000 0010 (2)
c. 0000 0011 (3)
d. 0000 0100 (4)
e. 0000 0101 (5)

정답: e

비트 OR(|) 연산자는 두 비트 중 하나라도 1이면 1이 됩니다.

0100 (4)
0001 (1)
   |
0101 (5)

(3) 5 ^ 1의 연산 결과로 올바른 것을 고르세요.

a. 0000 0001 (1)
b. 0000 0010 (2)
c. 0000 0011 (3)
d. 0000 0100 (4)
e. 0000 0101 (5)

정답: d

비트 XOR(^) 연산자는 두 비트가 다를 때 1이 됩니다.

0101 (5)
0001 (1)
   ^
0100 (4)

(4) 2 << 2 >> 1의 연산 결과로 올바른 것을 고르세요.

a. 0000 0001 (1)
b. 0000 0010 (2)
c. 0000 0011 (3)
d. 0000 0100 (4)
e. 0000 0101 (5)

정답: d

  • 왼쪽 시프트(<<)는 비트를 왼쪽으로 이동
  • 오른쪽 시프트(>>)는 비트를 오른쪽으로 이동
0010 (2)
   << 2
1000 (8)
   >> 1
0100 (4)

1.2 연습문제: 시프트 연산자 사용하기

다음 소스 코드를 완성하여 **4**가 출력되도록 하세요.

코드

using System;

class ShiftPractice
{
    static void Main()
    {
        Console.WriteLine(8 >> 3 << 2); // 4
    }
}

실행 결과

4

정답

2

해설

  • 8 (0000 1000)을 오른쪽으로 3번 이동하면 1 (0000 0001)이 됩니다.
  • 이를 다시 왼쪽으로 2번 이동하면 4 (0000 0100)이 됩니다.

1.1 퀴즈

(1) 다음 코드 실행 결과, 변수 two의 값으로 올바른 것을 고르세요.

int one = 1;
int two = 2;

two = (one > 1) ? 1111 : 2222;

a. 1
b. 2
c. 1111
d. 2222

정답: d

변수 one의 값이 1이므로 (1 > 1) 조건식은 거짓이 됩니다. 따라서 two 변수에는 2222가 저장됩니다.


(2) 다음 코드 실행 결과, 변수 result의 값으로 올바른 것을 고르세요.

int number = 1;
int result = 0;

result = 8 >> 2 * number++ - (3 % 2);

a. 1
b. 2
c. 4
d. 8

정답: c

연산자 우선순위에 따라 아래 순서대로 계산됩니다.

  1. (3 % 2)1
  2. 2 * number++2 (number는 이후 2가 됨)
  3. 2 - 11
  4. 8 >> 14 (비트 연산 8을 오른쪽으로 1비트 이동)
  5. result = 4

따라서 result 변수에는 4가 저장됩니다.


1.2 연습문제: 조건 연산자 사용하기

다음 소스 코드를 완성하여 **"점수: 59, 결과: 불합격"**이 출력되도록 하세요.

코드

using System;

class TernaryPractice
{
    static void Main()
    {
        int score = 59;
        string result = "";

        result = (score >= 60) ? "합격" : "불합격";

        Console.WriteLine($"점수: {score}, 결과: {result}");
    }
}

실행 결과

점수: 59, 결과: 불합격

정답

? :
또는
>= ? :
또는
== ? :

해설

조건 연산자(? :)는 3항 연산자라고도 하며,
(조건식) ? 값1 : 값2 형태로 사용됩니다.

  • score >= 60 조건식이 참이면 "합격"을 반환하고,
  • 거짓이면 "불합격"을 반환합니다.

주어진 값이 59이며, "불합격"이 출력되어야 하므로 조건식이 거짓이 되는 연산자 (>, >=, == 등)를 사용할 수 있습니다.

VisualAcademy Docs의 모든 콘텐츠, 이미지, 동영상의 저작권은 박용준에게 있습니다. 저작권법에 의해 보호를 받는 저작물이므로 무단 전재와 복제를 금합니다. 사이트의 콘텐츠를 복제하여 블로그, 웹사이트 등에 게시할 수 없습니다. 단, 링크와 SNS 공유, Youtube 동영상 공유는 허용합니다. www.VisualAcademy.com
박용준 강사의 모든 동영상 강의는 데브렉에서 독점으로 제공됩니다. www.devlec.com