부호 없는 오른쪽 시프트 연산자
메모
이 문서는 기능 사양입니다. 사양은 기능의 디자인 문서 역할을 합니다. 여기에는 기능 디자인 및 개발 중에 필요한 정보와 함께 제안된 사양 변경 내용이 포함됩니다. 이러한 문서는 제안된 사양 변경이 완료되고 현재 ECMA 사양에 통합될 때까지 게시됩니다.
기능 사양과 완료된 구현 간에 약간의 불일치가 있을 수 있습니다. 이러한 차이는 관련 언어 디자인 모임(LDM) 기록에서 기록됩니다.
사양문서에서 기능 명세를 C# 언어 표준으로 채택하는 과정을 자세히 알아볼 수 있습니다.
요약
부호 없는 오른쪽 시프트 연산자는 C#에서 기본 제공 연산자(기본 정수 형식의 경우) 및 사용자 정의 연산자로 지원됩니다.
동기
부호 있는 정수 값으로 작업할 때, 상위 비트를 반복 복사하지 않고 비트를 오른쪽으로 이동해야 하는 경우가 드물지 않습니다. 이는 일반 시프트 연산자를 사용하는 기본 정수 계열 형식에 대해 수행할 수 있지만, 시프트 작업 전에 부호 없는 형식으로 캐스팅하고, 시프트 작업 후에는 다시 원래 형식으로 캐스팅하는 것이 필요합니다. 라이브러리가 제공하려는 제네릭 수학 인터페이스의 컨텍스트 내에서, 형식에 대해 일반 수학 코드에 의해 미리 정의되거나 알려진 부호 없는 상대가 없을 수 있습니다. 그러나 알고리즘은 부호 없는 오른쪽 시프트 작업을 수행할 수 있는 기능에 의존할 수 있으므로 잠재적으로 더 큰 문제가 될 수 있습니다.
상세 디자인
연산자 및 문장 부호
섹션 §6.4.6에 부호 없는 오른쪽 시프트 연산자인 >>>
연산자를 포함하도록 조정할 것입니다.
unsigned_right_shift
: '>>>'
;
unsigned_right_shift_assignment
: '>>>='
;
unsigned_right_shift 및 unsigned_right_shift_assignment 프로덕션의 토큰 간에는 어떤 종류의 문자도 허용되지 않습니다(공백도 아님). 이러한 프로덕션은 type_parameter_list목록을 올바르게 처리할 수 있도록 특별히 처리됩니다.
시프트 연산자
섹션 §12.11은 부호 없는 오른쪽 시프트 연산자인 >>>
연산자를 포함하도록 조정됩니다.
<<
, >>
및 >>>
연산자는 비트 시프트 작업을 수행하는 데 사용됩니다.
shift_expression
: additive_expression
| shift_expression '<<' additive_expression
| shift_expression right_shift additive_expression
| shift_expression unsigned_right_shift additive_expression
;
폼 x << count
또는 x >> count
또는 x >>> count
연산의 경우 이진 연산자 오버로드 확인(§12.4.5)이 적용되어 특정 연산자 구현을 선택합니다. 피연산자는 선택한 연산자의 매개 변수 형식으로 변환되고 결과 형식은 연산자의 반환 형식입니다.
미리 정의된 서명되지 않은 시프트 연산자는 현재 구현에서 현재 미리 정의된 시프트 연산자가 지원하는 것과 동일한 서명 집합을 지원합니다.
오른쪽으로 이동:
int operator >>>(int x, int count); uint operator >>>(uint x, int count); long operator >>>(long x, int count); ulong operator >>>(ulong x, int count); nint operator >>>(nint x, int count); nuint operator >>>(nuint x, int count);
>>>
연산자는 아래 설명된 대로 계산된 비트 수만큼x
오른쪽으로 이동합니다.낮은 순서의
x
비트가 삭제되고, 나머지 비트가 오른쪽으로 이동되고, 빈 상위 비트 위치가 0으로 설정됩니다.
미리 정의된 연산자의 경우 이동할 비트 수는 다음과 같이 계산됩니다.
-
x
의 유형이int
또는uint
인 경우, 시프트 수는count
의 하위 5비트에 의해 제공됩니다. 즉, 시프트 수는count & 0x1F
에서 계산됩니다. -
x
의 유형이long
또는ulong
일 때, 시프트 수는count
의 하위 6비트에 의해 결정됩니다. 즉, 시프트 수는count & 0x3F
에서 계산됩니다.
결과 시프트 수가 0이면 시프트 연산자는 단순히 x
값을 반환합니다.
Shift 작업은 오버플로를 유발하지 않으며 checked
및 unchecked
컨텍스트에서 동일한 결과를 생성합니다.
대입 연산자
섹션 §12.21 조항이 다음과 같이 unsigned_right_shift_assignment를 포함하도록 조정됩니다.
assignment_operator
: '='
| '+='
| '-='
| '*='
| '/='
| '%='
| '&='
| '|='
| '^='
| '<<='
| right_shift_assignment
| unsigned_right_shift_assignment
;
정수 계열 형식
정수 타입 §8.3.6 섹션은 >>>
연산자에 대한 정보를 포함하도록 조정될 것입니다. 관련 글머리 기호는 다음과 같습니다.
- 이진
<<
,>>
및>>>
연산자의 경우 왼쪽 피연산자는T
형식으로 변환됩니다. 여기서T
피연산자의 가능한 모든 값을 완전히 나타낼 수 있는int
,uint
,long
및ulong
첫 번째입니다. 그런 다음T
형식의 정밀도를 사용하여 작업을 수행하고 결과의 형식은T
입니다.
상수 식
연산자 >>>
§12.23상수 식에 허용되는 구문 집합에 추가됩니다.
연산자 오버로딩
연산자 >>>
§12.4.3오버로드 가능한 이진 연산자 집합에 추가됩니다.
리프트 연산자
연산자 >>>
는 §12.4.8에서 승격된 형태를 허용하는 이진 연산자 집합에 추가됩니다.
연산자 우선 순위 및 결합성
섹션 §12.4.2 "Shift" 범주에 >>>
연산자를 추가하고 "할당 및 람다 식" 범주에 >>>=
연산자를 추가하도록 조정됩니다.
문법 모호성
>>>
연산자는 §6.2.5에서 설명된 것처럼 일반적인 >>
연산자와 동일한 문법적 모호성이 존재합니다.
연산자
§15.10 섹션은 >>>
연산자를 포함하도록 조정됩니다.
overloadable_binary_operator
: '+' | '-' | '*' | '/' | '%' | '&' | '|' | '^' | '<<'
| right_shift | unsigned_right_shift | '==' | '!=' | '>' | '<' | '>=' | '<='
;
이진 연산자
>>>
연산자의 서명에는 연산자의 서명에 대한 >>
것과 동일한 규칙이 적용됩니다.
메타데이터 이름
ECMA-335의 항목 "I.10.3.2 이진 연산자"에서는 부호 없는 오른쪽 시프트 연산자를 위한 이름 op_UnsignedRightShift가 이미 정해졌습니다.
Linq 표현식 트리
서명된 형식에 대한 미리 정의된 >>>
연산자의 의미 체계는 서명되지 않은 형식으로 변환하고 다시 원래대로 되돌리지 않으면 정확하게 나타낼 수 없으므로, Linq 식 트리에서 >>>
연산자는 지원되지 않습니다. 자세한 내용은 https://github.com/dotnet/csharplang/blob/main/meetings/2022/LDM-2022-02-09.md#unsigned-right-shift-operator 참조하세요.
동적 바인딩
동적 바인딩은 System.Linq.Expressions.ExpressionType 열거형의 값을 사용하여 런타임 바인더에 이진 연산자 종류를 전달하는 것처럼 보입니다. 부호 없는 오른쪽 시프트 연산자를 나타내는 멤버가 없으므로 >>>
연산자에 대한 동적 바인딩은 지원되지 않으며 정적 및 동적 바인딩(§12.3) 섹션이 이를 반영하도록 조정됩니다.
단점
대안
Linq 표현식 트리
>>>
연산자는 Linq Expressioin 트리에서 지원됩니다.
- 사용자 정의 연산자의 경우 연산자 메서드를 가리키는 BinaryExpression 노드가 만들어집니다.
- 미리 정의된 연산자
- 첫 번째 피연산자는 부호 있는 형식이면 BinaryExpression 노드가 만들어집니다.
- 첫 번째 피연산자가 부호 있는 형식인 경우, 첫 번째 피연산자가 부호 없는 형식으로 변환되고, BinaryExpression 노드가 생성된 후 결과가 부호 있는 형식으로 다시 변환됩니다.
예를 들어:
Expression<System.Func<int, int, int>> z = (x, y) => x >>> y; // (x, y) => Convert((Convert(x, UInt32) >> y), Int32)
Resolution:
거부됨, 자세한 내용은 https://github.com/dotnet/csharplang/blob/main/meetings/2022/LDM-2022-02-09.md#unsigned-right-shift-operator 참조하세요.
해결되지 않은 질문
디자인 회의
https://github.com/dotnet/csharplang/blob/main/meetings/2022/LDM-2022-02-09.md
C# feature specifications