12 비트 연산자와 시프트 연산자로 비트 단위 연산하기
이번 강의에서는 변수의 값을 비트 단위로 연산하는 비트 연산자와 시프트 연산자의 사용법을 다룹니다.
// 비트 연산자: & (비트단위 AND), | (비트단위 OR), ^ (비트단위 XOR), ~ (비트단위 NOT)
// 시프트 연산자: << (왼쪽 시프트), >> (오른쪽 시프트), >>> (부호 없는 오른쪽 시프트)
책읽기: 비트 연산자와 시프트 연산자로 비트 단위 연산하기 강의 소개
12.1 비트 연산자와 시프트 연산자의 종류
비트 연산자와 시프트 연산자는 2진수 비트 단위로 연산을 수행하는 데 사용됩니다. 우선 비트 연산자와 시프트 연산자의 7가지 종류를 표로 간단히 살펴본 후 진행하겠습니다.
[표] 비트 연산자와 시프트 연산자의 종류
연산자 | 별칭 | 설명 |
---|---|---|
& | 비트단위 AND | 비트 값이 둘 다 1일 때에만 1, 그렇지 않으면 0 |
| | 비트단위 OR | 비트 값이 하나라도 1이면 1, 그렇지 않으면 0 |
^ | 비트단위 XOR | 비트 값이 서로 다를 때에만 1, 그렇지 않으면 0 |
~ | 비트단위 NOT | 비트 값이 1이면 0, 0이면 1로 반전 |
<< | 왼쪽 시프트 | 비트 값을 지정된 수만큼 왼쪽으로 이동 |
>> | 오른쪽 시프트 | 비트 값을 지정된 수만큼 오른쪽으로 이동 |
>>> | 부호 없는 오른쪽 시프트 | 비트 값을 지정된 수만큼 오른쪽으로 이동하되 왼쪽을 0으로 채움 |
12.2 비트 연산자
비트 연산자(Bit Operator)는 정수형 데이터의 값을 이진수의 비트 단위로 연산을 수행하고자 할 때 사용됩니다. 비트 연산자는 다음과 같이 4개의 기호를 사용합니다. 좀 더 구분을 짓기 위해서 영문 단어를 추가했습니다.
- &
- 논리곱(AND, Both)
- |
- 논리합(OR, Either)
- ^
- 배타적 논리합(XOR; Exclusive OR, Different)
- ~
- NOT(Negation, Invert)
비트 연산자 AND, OR, XOR 간단 소개 동영상
12.3 Windows 계산기를 사용하여 이진수 비트 연산자 4개에 대한 실행 결과 살펴보기
Windows OS에 내장된 계산기를 사용하면 표준, 공학용, 프로그래머용 등의 여러 가지 환경을 사용할 수 있습니다.
그림: 계산기
12.4 비트 AND 연산자: & 연산자
본격적으로 비트 연산자를 사용하도록 하겠습니다. 먼저, 비트 AND 연산자인 & 연산자를 사용해 보겠습니다. 다음 코드를 주석을 제외하고 작성 후 실행해보세요.
그림: 계산기로 AND 연산 수행하기
코드: BitAnd.java
// & 연산자: 비트 AND 연산자(둘 다 1일 때만 1)
byte x = 0b1010; // 10
byte y = 0b1100; // 12
// x를 이진수로 표현 -> 십진수로 표현
System.out.println(" " + Integer.toBinaryString(x) + " -> " + x);
// y를 이진수로 표현 -> 십진수로 표현
System.out.println("& " + Integer.toBinaryString(y) + " -> " + y);
// x AND y를 이진수로 표현 -> 십진수로 표현
System.out.println(" " + Integer.toBinaryString(x & y) + " -> " + (x & y));
비트 AND
연산자인 &
연산자처럼 항을 2개 갖는 2항 연산자는 앞뒤로 공백을 두면 가독성이 좋아집니다. 즉, x & y
형태를 추천합니다.
12.5 비트 OR 연산자: | 연산자
이번에는 비트 OR
연산자인 |
연산자를 사용해 보겠습니다. |
연산자는 키보드의 파이프 기호(버티컬 바)를 사용합니다.
그림: 계산기로 OR 연산 수행하기
코드: BitOr.java
// | 연산자: 비트 OR 연산자(하나라도 1이면 1)
byte x = 0b1010; // 10
byte y = 0b1100; // 12
// x를 이진수로 표현 -> 십진수로 표현
System.out.println(" " + Integer.toBinaryString(x) + " -> " + x);
// y를 이진수로 표현 -> 십진수로 표현
System.out.println("| " + Integer.toBinaryString(y) + " -> " + y);
// x OR y를 이진수로 표현 -> 십진수로 표현
System.out.println(" " + Integer.toBinaryString(x | y) + " -> " + (x | y));
나중에 프로그래머로 일하다 보면 이진수 처리가 중요한 분야가 있을 수 있습니다. 하지만, 처음 학습자에게는 "이런 연산자를 사용하면 이렇게 나오는구나" 정도로 알고 넘어가는 것이 좋습니다.
비트 XOR 연산자: ^
연산자
비트 XOR
연산자인 ^
연산자는 두 비트의 값이 서로 다를 때 1
입니다. 1 ^ 0
과 0 ^ 1
일 때에만 1
이고 나머지는 0
입니다. XOR
은 엑스오어라고 읽습니다. ^
는 삿갓이라고 읽기도 하지만, 정확한 명칭은 캐럿(carat)입니다.
그림: 계산기로 XOR 연산 수행하기
코드: BitXor.java
// ^ 연산자: 비트 XOR 연산자(서로 다르면 1)
public class BitXor {
public static void main(String[] args) {
byte x = 0b1010; // 10
byte y = 0b1100; // 12
// x를 이진수로 표현 -> 십진수로 표현
System.out.println(String.format(" %s -> %d", Integer.toBinaryString(x & 0xFF), x));
// y를 이진수로 표현 -> 십진수로 표현
System.out.println(String.format("^ %s -> %d", Integer.toBinaryString(y & 0xFF), y));
// x XOR y를 이진수로 표현 -> 십진수로 표현
System.out.println(String.format(" %s -> %d", Integer.toBinaryString((x ^ y) & 0xFF).padStart(4, '0'), x ^ y));
}
}
비트 NOT 연산자: ~
연산자
비트 NOT
연산자인 ~
연산자는 물결(틸드) 기호를 사용합니다. ~
연산자는 비트 값이 1
이면 0
으로, 0
이면 1
로 바꿉니다. 이렇게 비트가 바뀌는 것이 비트 반전입니다.
그림: 계산기로 비트 반전
코드: BitNot.java
// ~ 연산자: 비트 NOT 연산자(1 <-> 0, 비트 반전)
public class BitNot {
public static void main(String[] args) {
byte x = 0b00001010; // 10
// x를 8자리 이진수로 표현 -> 십진수로 표현
System.out.println(String.format("~ %s -> %3d", Integer.toBinaryString(x & 0xFF).padStart(8, '0'), x));
// NOT x를 8자리 이진수로 표현 -> 십진수로 표현
System.out.println(String.format(" %s -> %3d", Integer.toBinaryString(~x & 0xFF).padStart(8, '0'), ~x));
}
}
Java에서는 비트 NOT 연산자를 사용할 때 주의해야 합니다. Java에서는 모든 정수 타입이 부호 있는(signed) 정수이기 때문에, byte
를 비트 NOT 연산한 결과는 int
타입으로 자동 확장되며, 결과가 음수가 될 수 있습니다. 따라서, byte
타입의 결과를 얻기 위해서는 결과를 명시적으로 byte
타입으로 캐스팅하거나, 결과를 다룰 때 주의해야 합니다.
비트 연산자 4가지 모두 사용해보기
이번에는 비트 연산자 네 가지를 모아서 사용해보겠습니다.
코드: BitwiseOperator.java
// 비트 연산자: &, |, ~, ^
public class BitwiseOperator {
public static void main(String[] args) {
int x = Integer.parseInt("1010", 2); // 10
int y = Integer.parseInt("0110", 2); // 6
int and = x & y;
System.out.println(String.format("%d : %s", and, Integer.toBinaryString(and)));
int or = x | y;
System.out.println(String.format("%d : %s", or, Integer.toBinaryString(or)));
int xor = x ^ y;
System.out.println(String.format("%d : %s", xor, Integer.toBinaryString(xor)));
int not = ~x;
System.out.println(String.format("%d : %s", not, Integer.toBinaryString(not)));
}
}
12.8 시프트 연산자
시프트 연산자(Shift Operator)는 정수 데이터가 담겨 있는 메모리의 비트를 왼쪽(<<
) 또는 오른쪽(>>
)으로 지정한 비트만큼 이동시켜주는 기능을 제공합니다. Java에서는 >>>
연산자도 제공하는데, 이는 부호없이 오른쪽으로 비트를 이동시키는 연산자입니다.
시프트 연산자를 사용하면 비트의 자리를 다음과 같이 이동할 수 있습니다.
x << y
:x
를y
만큼 왼쪽으로 이동x >> y
:x
를y
만큼 오른쪽으로 이동, 부호 비트는 유지x >>> y
:x
를y
만큼 오른쪽으로 이동, 왼쪽을 0으로 채움
코드: ShiftOperatorDemo.java
public class ShiftOperatorDemo {
public static void main(String[] args) {
int number = 2; // 0010
System.out.println(number << 1); // 0010 -> 0100 : 4
System.out.println(number >> 1); // 0010 -> 0001 : 1
System.out.println(number >>> 1); // 0010 -> 0001 : 1
}
}
Java에서 시프트 연산자를 사용할 때, >>>
연산자는 부호 비트를 무시하고 항상 0으로 채우는 오른쪽 시프트를 수행합니다. 이는 특히 음수를 다룰 때 유용할 수 있습니다.
부호 없는 오른쪽 시프트 연산자 >>>
Java에서는 오른쪽 시프트 연산자에 산술 오른쪽 시프트 연산자(>>
)와 부호 없는 오른쪽 시프트 연산자(>>>
)의 두 가지 형태가 있습니다. >>>
연산자는 부호 없는 오른쪽 시프트 연산자로, 왼쪽 피연산자를 오른쪽 피연산자가 지정한 비트 수만큼 오른쪽으로 이동시키며, 상위 비트 위치를 항상 0으로 설정합니다. 이는 피연산자의 유형이 부호 있는 정수형일지라도 동일하게 적용됩니다.
다음 코드는 음수 값을 오른쪽으로 시프트하는 부호 없는 오른쪽 시프트 연산자의 사용 예제를 보여줍니다.
코드: UnsignedRightShiftExample
public class UnsignedRightShiftExample {
public static void main(String[] args) {
int x = -4;
System.out.printf("이전: %11d, 2진수: %32s%n", x, Integer.toBinaryString(x));
int y = x >> 1;
System.out.printf(">> 이후: %11d, 2진수: %32s%n", y, Integer.toBinaryString(y));
int z = x >>> 1;
System.out.printf(">>> 이후: %11d, 2진수: %32s%n", z, Integer.toBinaryString(z));
}
}
이전: -4, 2진수: 11111111111111111111111111111100
>> 이후: -2, 2진수: 11111111111111111111111111111110
>>> 이후: 2147483646, 2진수: 01111111111111111111111111111110
이 예제에서는 -4
라는 음수 값인 x
변수를 사용합니다. 먼저, x
의 이진수 표현을 출력한 다음, 산술 오른쪽 시프트 연산자(>>
)를 사용하여 x
를 1비트 오른쪽으로 시프트하고 그 결과를 y
에 저장하여 출력합니다. 마지막으로, 부호 없는 오른쪽 시프트 연산자(>>>
)를 사용하여 x
를 1비트 오른쪽으로 시프트하고 그 결과를 z
에 저장하여 출력합니다.
여기서 x
는 -4
이며, 이진 표현은 11111111111111111111111111111100
입니다. x
에 >>> 1
연산을 적용하면, 이진 표현을 오른쪽으로 한 비트 이동시키고 왼쪽에 0
을 추가합니다. 따라서 결과는 01111111111111111111111111111110
이며, 이는 10진수로 2147483646
입니다.
이 예제를 통해 산술 오른쪽 시프트 연산자(>>
)는 최상위 비트(부호 비트)를 유지하며 시프트를 수행하는 반면, 부호 없는 오른쪽 시프트 연산자(>>>
)는 상위 빈 비트 위치를 항상 0
으로 설정하고 시프트를 수행한다는 점을 확인할 수 있습니다. 이로 인해 부호 없는 오른쪽 시프트 연산자(>>>
)를 사용할 경우 음수 값이 양수 값으로 변환될 수 있습니다.
비트 연산자와 시프트 연산자를 할당 연산자와 함께 사용하기
비트 연산자와 시프트 연산자도 할당 연산자와 함께 사용할 수 있습니다. 사용 방법은 일반적인 할당 연산자와 동일합니다.
A &= B;
A |= B;
A ^= B;
A <<= B;
A >>= B;
A >>>= B;
(Java에서는 부호 없는 오른쪽 시프트 할당 연산자도 있습니다.)
이번에는 할당 연산자와 함께 비트 연산자, 시프트 연산자를 사용해 보겠습니다.
코드: BitwiseAssignment.java
public class BitwiseAssignment {
public static void main(String[] args) {
byte num1 = 4; // 4: 00000100
num1 &= 5; // 5(0101) & 4(0100) => 4(00000100)
System.out.println(num1); // 4
byte num2 = 4; // 4: 00000100
num2 |= 1; // 1(0001) | 4(0100) => 5(00000101)
System.out.println(num2); // 5
byte num3 = 4; // 4: 00000100
num3 ^= 2; // 2(0010) ^ 4(0100) => 6(00000110)
System.out.println(num3); // 6
byte num4 = 4; // 4: 00000100
num4 <<= 1; // 4(0100) << 1 => 8(00001000)
System.out.println(num4); // 8
byte num5 = 4; // 4: 00000100
num5 >>= 1; // 4(0100) >> 1 => 2(00000010)
System.out.println(num5); // 2
byte num6 = (byte)0b10000000; // -128 in two's complement
num6 >>>= 1; // 부호 없는 오른쪽 시프트 할당 연산자 사용
System.out.println(num6); // 64 (00000010)
}
}
결과는 각 비트 연산 후 그 결괏값을 다시 변수에 할당한 내용이 출력됩니다. 비트 연산자와 시프트 연산자는 하드웨어 제어나 저수준 프로그래밍에서 유용하게 사용됩니다. Java에서도 이러한 연산자들을 통해 성능 최적화나 특정 비트 레벨에서의 데이터 처리 작업을 수행할 수 있습니다. 그러나 일반적인 애플리케이션 개발에서는 자주 사용되지 않으므로, 이번 예제의 내용을 이해하고 넘어가면 충분합니다.
기타 연산자 사용하기 및 연산자 우선순위 알아보기
이번 강의에서는 3항 연산자와 나머지 연산자를 살펴보고, 연산자들의 우선순위에 대해 알아보겠습니다.
// 조건 연산자(3항 연산자): "조건식 ? 조건식이참일때의값 : 조건식이거짓일때의값"
조건 연산자
물음표와 콜론 기호를 함께 사용하는 "? :"
형태의 모양을 갖는 조건 연산자(Conditional Operator)는 조건에 따라 참(true)일 때와 거짓(false)일 때의 결과를 다르게 반환하고자 할 때 사용됩니다. 조건 연산자는 항이 3개여서 3항 연산자(Ternary Operator)라고도 합니다. 3항 연산자는 if ~ else
문의 축약형이라고 볼 수 있습니다.
(5 > 3) ? "TRUE" : "FALSE"; // "TRUE"
3항 연산자인 ?:
연산자는 조건을 처리합니다.
조건식 ? 식1 : 식2;
조건식이 참이면 식1이 실행되고, 조건식이 거짓이면 식2가 실행됩니다.
3항 연산자의 결괏값이 특정 값을 반환하기 때문에, 다음과 같이 사용됩니다.
조건식 ? 값1 : 값2;
?:
연산자 보충 설명
3개의 항을 가진 조건 연산자라고 하는 ?:
연산자는 부울 식을 평가하고, 부울 식이 true
또는 false
로 계산되는지에 따라 두 식 중 하나의 결과를 반환합니다.
String message = (tempInCelsius < 20.0) ? "Cold." : "Perfect!";
조건 연산자의 구문은 다음과 같습니다.
condition ? consequent : alternative
condition
식은 true
또는 false
로 계산되어야 합니다. condition
이 true
로 계산되면 consequent
식이 계산되고 해당 결과가 연산의 결과가 됩니다. condition
이 false
로 계산되면 alternative
식이 계산되고 해당 결과가 연산의 결과가 됩니다. consequent
또는 alternative
중 하나만 계산됩니다.
조건부 연산자는 오른쪽으로 연결됩니다. 즉, 다음 형식의 식을 가정해 보겠습니다.
a ? b : c ? d : e
이 식은 다음과 같이 계산됩니다.
a ? b : (c ? d : e)
팁: 다음과 같은 기억법을 사용하여 조건부 연산자의 평가 방식을 기억할 수 있습니다.
이 조건이 참인가? 참이면 여기 : 거짓이면 여기
조건 연산자 사용하기
3항 연산자인 조건 연산자의 사용법을 살펴보겠습니다.
코드: ConditionalOperator.java
// [?] 3항 연산자(조건 연산자) 사용하기
int number = 3;
// number가 짝수면 result 변수에 "짝수" 담고 그렇지 않으면 "홀수" 담기
String result = (number % 2 == 0) ? "짝수" : "홀수";
System.out.println(number + "은(는) " + result + "입니다.");
// 출력: 3은(는) 홀수입니다.
number
변수에 3
을 넣어 놓은 후, (number % 2 == 0)
을 평가하면 거짓(false
)이 됩니다. 물음표(?
) 기호 앞의 식이 false
이므로 "홀수"가 result
변수에 담깁니다. 즉, 조건식이 참이면 "짝수"를 반환하고, 그렇지 않으면 "홀수"를 반환합니다.
조건 연산자를 사용하여 최댓값 정하기
이번에는 조건 연산자를 사용하여 최댓값을 우리가 원하는 값으로 정하는 방법을 알아보겠습니다.
코드: OperatorMaxSize.java
// [?] 들어오는 값이 20 이상이면 20으로 초기화, 20 미만이면 해당 값으로 초기화
final int maxSize = 20; // 최댓값을 20으로 정함
int pageSize = 0;
pageSize = 10;
pageSize = (pageSize > maxSize) ? maxSize : pageSize; // 10
System.out.println(pageSize); // 10
pageSize = 50;
pageSize = (pageSize > maxSize) ? maxSize : pageSize; // 20
System.out.println(pageSize); // 20
pageSize
변수에 들어오는 값이 20
보다 작으면 그 값 그대로, 20
이상이면 20
으로 고정하는 기능을 구현해 보았습니다.
조건 연산자를 사용하여 문자 크기 비교하기
이번에는 조건 연산자를 사용하여 문자의 크기를 비교해 보겠습니다.
코드: TernaryOperator.java
String result = "";
// 'A'는 'B'보다 작으므로 참이므로 앞의 문자열이 result 변수에 저장
result = ('A' < 'B') ? "'A'는 'B'보다 작습니다." : "'A'와 'B'는 크기가 같습니다.";
System.out.println(result); // "'A'는 'B'보다 작습니다."
// 'Z'는 'a'보다 작으므로 참이므로 앞의 문자열이 result 변수에 저장
result = ('Z' < 'a') ? "'Z'는 'a'보다 작습니다." : "대문자가 소문자보다 큽니다.";
System.out.println(result); // "'Z'는 'a'보다 작습니다."
프로그래밍 언어에서는 A, B, C, …, Z, a, b, c, …, z
순서로 크기가 정해져 있습니다. 이러한 크기를 조건 연산자의 조건식에 두고 크기를 비교해 보았습니다.
조건(3항) 연산자로 절댓값 구하기
조건 연산자인 3항 연산자를 사용하면 다음 코드와 같이 정수의 절댓값을 쉽게 구할 수 있습니다.
코드: AbsoluteValue.java
int num = -21; // 음수 값을 저장
int abs = (num < 0) ? -num : num; // 3항 연산자로 음수만 부호 변환
System.out.println(num + "의 절댓값: " + abs); // -21의 절댓값: 21
나열
(콤마) 연산자
변수를 선언할 때 이미 다루었지만, 콤마를 구분자로 하여 하나의 문장에 여러 개의 변수 선언문을 지정할 때 사용합니다. 이러한 콤마 연산자(Comma Operator)를 나열 연산자라고도 합니다. 나열 연산자는 다음과 같이 사용됩니다.
int a = 10, b = 20, c = 30;
위와 같이 콤마로 여러 개의 할당문이 지정되면, a, b, c
변수 모두 int
타입 변수로 선언됩니다.
IMPORTANT
콤마 연산자는 코드가 복잡해질 수 있기에 가능하면 사용하지 않습니다.
sizeof
연산자로 데이터 타입의 크기 구하기
Java에서는 sizeof
연산자가 직접적으로 제공되지 않습니다. 대신, 자바의 기본 데이터 타입들의 크기는 표준화되어 있습니다. 예를 들어, int
는 항상 32비트(4바이트)입니다. 그러나, 실제 메모리 사용량을 알고 싶다면, Java의 특정 라이브러리나 도구를 사용해야 합니다. 자바에서는 객체의 크기를 직접 얻기 위한 표준 방법이 없으므로, 예시 코드 대신 Java에서 기본 데이터 타입의 크기에 대한 정보를 제공합니다.
기본 데이터 타입 크기
byte
: 8비트(1바이트)char
: 16비트(2바이트)int
: 32비트(4바이트)long
: 64비트(8바이트)float
: 32비트(4바이트)double
: 64비트(8바이트)
Java에서 객체의 메모리 크기를 추정하려면, Java Instrumentation API와 같은 도구를 사용해야 합니다. 또는, 실행 시간에 Java Virtual Machine(JVM)의 관리 빈(Management Beans)을 통해 간접적으로 메모리 사용량을 모니터링할 수 있습니다.
연산자 우선 순위
Java에서도 여러 개의 연산자를 사용할 때 연산자의 우선순위에 따라 계산됩니다. 예를 들어, 산술 연산자에서 +
보다 *
가 더 높은 우선순위를 가집니다. 괄호 연산자 ()
를 사용하면 우선순위를 변경할 수 있습니다.
Java의 연산자 우선순위는 C#과 매우 유사합니다. 가장 높은 우선순위부터 낮은 우선순위까지 다음과 같은 순서를 따릅니다:
- 괄호
()
(높은 우선순위) - 증감 연산자
++, --
- 단항 연산자
+
,-
(음수, 양수 표시) - 산술 연산자
*
,/
,%
- 산술 연산자
+
,-
- 비교 연산자
<
,>
,<=
,>=
- 등가 연산자
==
,!=
- 비트 연산자
&
,^
,|
- 논리 연산자
&&
,||
- 조건 연산자
?:
- 할당 연산자
=
,+=
,-=
,*=
,/=
,%=
등 (낮은 우선순위)
연산자 우선순위에 대해 외우려고 애쓰기보다는, 코드의 명확성을 위해 괄호를 적절히 사용하는 것이 좋습니다.
다음은 연산자 우선순위를 보여주는 Java 코드 예시입니다:
public class OperatorPrecedence {
public static void main(String[] args) {
System.out.println(3 + 4 * 2); // 출력: 11
System.out.println((3 + 4) * 2); // 출력: 14
System.out.println(10 / 5 * 2 + 1); // 출력: 5
System.out.println(15 / (5 * (2 + 1))); // 출력: 1
}
}
이렇게, Java에서는 기본 데이터 타입의 크기가 고정되어 있으며, 연산자 우선순위는 C#과 유사하게 작동합니다. 연산자 우선순위를 잘 이해하고 사용하면, 복잡한 표현식을 보다 명확하게 작성할 수 있습니다.
정보처리산업기사 실기 시험 기출 문제 - 비트 및 논리 연산 출력
문제
다음 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
의 값에 대한 여러 가지 비트 연산 및 논리 연산을 수행하고 그 결과를 출력합니다.
int x = 1;
는 정수 변수x
를 선언하고 1로 초기화합니다.Console.WriteLine(!(x > 0));
는x > 0
의 조건이 참이므로,!
연산자를 사용하여 그 결과를 반전시킵니다. 따라서False
가 출력됩니다.Console.WriteLine(x > 0 || x < 4);
는x > 0
또는x < 4
의 조건 중 하나라도 참이면True
를 반환합니다. 두 조건 모두 참이므로,True
가 출력됩니다.Console.WriteLine(x << 2);
는x
의 값을 왼쪽으로 2비트 이동시킵니다.x
의 값인 1을 2진수로01
로 표현할 때, 왼쪽으로 2비트 이동시키면100
이 되어, 10진수로 4가 됩니다. 따라서4
가 출력됩니다.Console.WriteLine(x & 2);
는x
의 값과 2를 비트 AND 연산합니다.x
의 2진수 값01
과 2의 2진수 값10
을 AND 연산하면00
이 되어, 10진수로 0이 됩니다. 따라서0
이 출력됩니다.Console.WriteLine(x % 3);
는x
를 3으로 나눈 나머지를 출력합니다. 1을 3으로 나눈 나머지는 1이므로,1
이 출력됩니다.
이 프로그램은 기본적인 비트 연산과 논리 연산을 통해 다양한 결과를 출력하며, 조건 연산자와 비트 이동 연산자 등의 사용 방법을 이해하는 데 도움을 줍니다. C#에서는 논리 연산 결과를 대문자 True
와 False
로 출력하는 것을 제외하고는 Java와 매우 유사한 동작을 합니다.