다음을 통해 공유


Numeric IntPtr

메모

이 문서는 기능 사양입니다. 사양은 기능의 디자인 문서 역할을 합니다. 여기에는 기능 디자인 및 개발 중에 필요한 정보와 함께 제안된 사양 변경 내용이 포함됩니다. 이러한 문서는 제안된 사양 변경이 완료되고 현재 ECMA 사양에 통합될 때까지 게시됩니다.

기능 사양과 완료된 구현 간에 약간의 불일치가 있을 수 있습니다. 이러한 차이는 관련된 LDM(언어 디자인 모임) 노트에 기록됩니다.

규격문서에서 C# 언어 표준으로 기능 사양을 채택하는 과정에 대해 자세히 알아볼 수 있습니다.

챔피언 이슈: https://github.com/dotnet/csharplang/issues/6065

요약

이는 nint/nuint 형식이 System.IntPtr/System.UIntPtr기본 형식과 구별되는 초기 네이티브 정수 기능(사양)에 대한 수정 버전입니다. 요컨대, 이제 nint/nuintSystem.Int32관련하여 int 경우처럼 System.IntPtr/System.UIntPtr별칭을 지정하는 간단한 형식으로 취급합니다. System.Runtime.CompilerServices.RuntimeFeature.NumericIntPtr 런타임 기능 플래그는 이 새로운 동작을 트리거합니다.

디자인

8.3.5 단순 형식

C#은 단순 형식이라는 미리 정의된 struct 형식 집합을 제공합니다. 단순 형식은 키워드를 통해 식별되지만 이러한 키워드는 아래 표에 설명된 대로 System 네임스페이스의 미리 정의된 struct 형식에 대한 별칭일 뿐입니다.

키워드 별칭 형식
sbyte System.SByte
byte System.Byte
short System.Int16
ushort System.UInt16
int System.Int32
uint System.UInt32
nint System.IntPtr
nuint System.UIntPtr
long System.Int64
ulong System.UInt64
char System.Char
float System.Single
double System.Double
bool System.Boolean
decimal System.Decimal

[...]

8.3.6 정수 계열 형식

C#은 sbyte, byte, short, ushort, int, uint, nint, nuint, long, ulong, char등 11개의 정수 계열 형식을 지원합니다. [...]

8.8 관리되지 않는 형식

즉, unmanaged_type 다음 중 하나입니다.

  • sbyte, byte, short, ushort, int, uint, nint, nuint, long, ulong, char, float, double, decimal또는 bool.
  • 모든 열거형 타입 .
  • 구성된 형식이 아니며 오직 unmanaged_type필드만 포함하는 사용자 정의 struct_type.
  • 안전하지 않은 코드에서는 pointer_type.

10.2.3 암시적 숫자 변환

암시적 숫자 변환은 다음과 같습니다.

  • sbyte에서 short, int, nint, long, float, double또는 decimal.
  • byte에서 short, ushort, int, uint, nint, nuint, long, ulong, float, double또는 decimal.
  • short부터 int, nint, long, float, double또는 decimal까지.
  • ushort에서 int, uint, nint, nuint, long, ulong, float, double또는 decimal.
  • int에서 nint, long, float, double또는 decimal.
  • uint부터 nuint, long, ulong, float, double또는 decimal까지.
  • nint에서 long, float, double또는 decimal.
  • nuint에서 ulong, float, double또는 decimal.
  • long에서 float, double또는 decimal로.
  • ulong에서 float, double또는 decimal.
  • char에서 ushort, int, uint, nint, nuint, long, ulong, float, double또는 decimal.
  • float부터 double.

[...]

10.2.11 암시적 상수 식 변환

암시적 상수 식 변환은 다음과 같은 변환을 허용합니다.

  • constant_expression 값이 대상 형식 범위 내에 있는 경우 형식 intconstant_expression 형식 sbyte, byte, short, ushort, uint, nint, nuint또는 ulong변환할 수 있습니다. [...]

10.3.2 명시적 숫자 변환

명시적 숫자 변환은 numeric_typenumeric_type으로 변환하는 것을 의미하며, 이는 암시적 숫자 변환이 존재하지 않는 경우입니다.

  • sbyte에서 byte, ushort, uint, nuint, ulong또는 char으로.
  • byte부터 sbyte 또는 char.
  • short에서 sbyte, byte, ushort, uint, nuint, ulong또는 char.
  • ushort에서 sbyte, byte, short또는 char까지.
  • int에서 sbyte, byte, short, ushort, uint, nuint, ulong또는 char.
  • uint에서 sbyte, byte, short, ushort, int, nint또는 char.
  • long에서 sbyte, byte, short, ushort, int, uint, nint, nuint, ulong또는 char.
  • nint에서 sbyte, byte, short, ushort, int, uint, nuint, ulong또는 char.
  • nuint에서 sbyte, byte, short, ushort, int, uint, nint, long또는 char.
  • ulong에서 sbyte, byte, short, ushort, int, uint, nint, nuint, long또는 char.
  • char부터 sbyte, byte또는 short.
  • float에서 sbyte, byte, short, ushort, int, uint, nint, nuint, long, ulong, char또는 decimal.
  • double에서 sbyte, byte, short, ushort, int, uint, nint, nuint, long, ulong, char, float또는 decimal.
  • decimal에서 sbyte, byte, short, ushort, int, uint, nint, nuint, long, ulong, char, float또는 double.

[...]

10.3.3 명시적 열거형 변환

명시적 열거형 변환은 다음과 같습니다.

  • sbyte, byte, short, ushort, int, uint, nint, nuint, long, ulong, char, float, double또는 decimal에서 임의의 enum_type로.
  • 어떤 enum_type 에서 sbyte, byte, short, ushort, int, uint, nint, nuint, long, ulong, char, float, double또는 decimal로.
  • enum_type에서 다른 enum_type로.

12.6.4.7 더 나은 변환 대상

두 가지 형식 T₁T₂이 주어졌을 때, T₁더 나은 변환 대상이 될 수 있습니다. 다음 중 하나가 성립하면: T₂.

  • T₁ T₂ 암시적 변환이 존재하며 T₂T₁ 암시적 변환이 없습니다.
  • T₁Task<S₁>이고, T₂Task<S₂>이며, S₁S₂보다 더 나은 변환 대상입니다.
  • T₁S₁ 또는 S₁?이며, S₁는 부호 있는 정수형입니다. 그리고 T₂S₂ 또는 S₂?이며, S₂는 부호 없는 정수형입니다. 구체적으로: [...]

12.8.12 요소 액세스

[...] argument_list 식 수는 array_type순위와 같아야 하며 각 식은 int, uint, nint, nuint, long또는 ulong, 형식이거나 이러한 형식 중 하나 이상으로 암시적으로 변환할 수 있어야 합니다.

11.8.12.2 배열 액세스

[...] argument_list 식 수는 array_type순위와 같아야 하며 각 식은 int, uint, nint, nuint, long또는 ulong, 형식이거나 이러한 형식 중 하나 이상으로 암시적으로 변환할 수 있어야 합니다.

[...] P[A]형식 배열 접근의 런타임 처리는 Pprimary_no_array_creation_expressionarray_type이고 Aargument_list인 경우, 다음 단계로 구성됩니다. [...]

  • argument_list 인덱스 식은 왼쪽에서 오른쪽으로 순서대로 평가됩니다. 각 인덱스 식을 평가한 후에는 int, uint, nint, nuint, long, ulong중 하나로 암시적으로 변환됩니다. 암시적 변환이 존재하는 이 목록의 첫 번째 형식이 선택됩니다. [...]

12.8.16 후위 증가 및 감소 연산자

단항 연산자 오버로드 확인은 특정 연산자 구현을 선택하기 위해 적용됩니다. 미리 정의된 ++-- 연산자는 sbyte, byte, short, ushort, int, uint, nint, nuint,long, ulong, char, float, double, decimal및 모든 열거형 형식에 대해 존재합니다.

12.9.2 단항 더하기 연산자

미리 정의된 단항 더하기 연산자는 다음과 같습니다.

...
nint operator +(nint x);
nuint operator +(nuint x);

12.9.3 단항 빼기 연산자

미리 정의된 단항 빼기 연산자는 다음과 같습니다.

  • 정수 부정:

    ...
    nint operator –(nint x);
    

12.8.16 후위 증가 및 감소 연산자

미리 정의된 ++-- 연산자는 sbyte, byte, short, ushort, int, uint, nint, nuint, long, ulong, char, float, double, decimal및 모든 열거형 형식에 대해 존재합니다.

11.7.19 기본값 식

또한 형식이 sbyte, byte, short, ushort, int, uint, nint, nuint, long, ulong, char, float, double, decimal, bool, 또는 열거형 형식 중 하나이면 default_value_expression 상수 식입니다.

12.9.5 비트 반전 연산자

미리 정의된 비트 보수 연산자는 다음과 같습니다.

...
nint operator ~(nint x);
nuint operator ~(nuint x);

12.9.6 접두사 증가 및 감소 연산자

미리 정의된 ++-- 연산자는 sbyte, byte, short, ushort, int, uint, nint, nuint, long, ulong, char, float, double, decimal및 모든 열거형 형식에 대해 존재합니다.

12.10 산술 연산자

12.10.2 곱하기 연산자

미리 정의된 곱셈 연산자는 아래에 나열되어 있습니다. 연산자는 모두 xy곱을 계산합니다.

  • 정수 곱하기:

    ...
    nint operator *(nint x, nint y);
    nuint operator *(nuint x, nuint y);
    

12.10.3 나눗셈 연산자

미리 정의된 나누기 연산자는 다음과 같습니다. 연산자는 모두 xy몫을 계산합니다.

  • 정수 나누기:

    ...
    nint operator /(nint x, nint y);
    nuint operator /(nuint x, nuint y);
    

12.10.4 나머지 연산자

미리 정의된 나머지 연산자는 아래에 나열되어 있습니다. 연산자는 모두 xy사이의 나머지 부분을 계산합니다.

  • 정수 나머지:

    ...
    nint operator %(nint x, nint y);
    nuint operator %(nuint x, nuint y);
    

12.10.5 더하기 연산자

  • 정수 추가:

    ...
    nint operator +(nint x, nint y);
    nuint operator +(nuint x, nuint y);
    

12.10.6 빼기 연산자

  • 정수 빼기:

    ...
    nint operator –(nint x, nint y);
    nuint operator –(nuint x, nuint y);
    

12.11 시프트 연산자

미리 정의된 시프트 연산자는 아래에 나열되어 있습니다.

  • 왼쪽으로 이동:

    ...
    nint operator <<(nint x, int count);
    nuint operator <<(nuint x, int count);
    
  • 오른쪽으로 이동:

    ...
    nint operator >>(nint x, int count);
    nuint operator >>(nuint x, int count);
    

    >> 연산자는 아래 설명된 대로 계산된 비트 수만큼 x 오른쪽으로 이동합니다.

    x 형식이 int, nint 또는 long경우 낮은 순서의 x 비트가 삭제되고, 나머지 비트는 오른쪽으로 이동하고, x 음수가 아니면 상위 빈 비트 위치가 0으로 설정되고 x 음수이면 1로 설정됩니다.

    x 형식이 uint, nuint 또는 ulong경우 낮은 순서의 x 비트가 삭제되고, 나머지 비트가 오른쪽으로 이동되고, 상위 빈 비트 위치가 0으로 설정됩니다.

  • 서명되지 않은 시프트 오른쪽:

    ...
    nint operator >>>(nint x, int count);
    nuint operator >>>(nuint x, int count);
    

미리 정의된 연산자의 경우 이동할 비트 수는 다음과 같이 계산됩니다. [...]

  • x 유형이 nint 또는 nuint시프트 수는 32비트 플랫폼의 하위 5비트 count 또는 64비트 플랫폼의 하위 6비트 count 의해 제공됩니다.

12.12 관계형 및 형식 테스트 연산자

12.12.2 정수 비교 연산자

미리 정의된 정수 비교 연산자는 다음과 같습니다.

...
bool operator ==(nint x, nint y);
bool operator ==(nuint x, nuint y);

bool operator !=(nint x, nint y);
bool operator !=(nuint x, nuint y);

bool operator <(nint x, nint y);
bool operator <(nuint x, nuint y);

bool operator >(nint x, nint y);
bool operator >(nuint x, nuint y);

bool operator <=(nint x, nint y);
bool operator <=(nuint x, nuint y);

bool operator >=(nint x, nint y);
bool operator >=(nuint x, nuint y);

12.12 논리 연산자

12.12.2 정수 논리 연산자

미리 정의된 정수 논리 연산자는 다음과 같습니다.

...
nint operator &(nint x, nint y);
nuint operator &(nuint x, nuint y);

nint operator |(nint x, nint y);
nuint operator |(nuint x, nuint y);

nint operator ^(nint x, nint y);
nuint operator ^(nuint x, nuint y);

12.22 상수 식

상수 식은 값 형식 또는 참조 형식일 수 있습니다. 상수 식이 값 형식인 경우 sbyte, byte, short, ushort, int, uint, nint, nuint, long, ulong, char, float, double, decimal, bool, 또는 열거형 형식 중 하나여야 합니다.

[...]

암시적 상수 식 변환을 사용하면 상수 식의 값이 대상 형식 범위 내에 있는 경우 sbyte, intbyte, short, ushort, uint, nint, nuint, 또는 ulong형식의 상수 식을 변환할 수 있습니다.

17.4 배열 요소 접근

배열 요소는 A[I₁, I₂, ..., Iₓ]양식의 element_access 식을 사용하여 액세스합니다. 여기서 A 배열 형식의 식이고 각 Iₑint, uint, nint, nuint,long, ulong형식의 식이거나 이러한 형식 중 하나 이상으로 암시적으로 변환될 수 있습니다. 배열 요소 액세스의 결과는 변수, 즉 인덱스에 의해 선택된 배열 요소입니다.

23.5 포인터 변환

23.5.1 일반

[...]

또한 안전하지 않은 컨텍스트에서는 다음과 같은 명시적 포인터 변환을 포함하도록 사용 가능한 명시적 변환 집합이 확장됩니다.

  • 어떠한 pointer_type에서 다른 pointer_type로.
  • sbyte, byte, short, ushort, int, uint, nint, nuint,long, 또는 ulong에서 pointer_type로.
  • 모든 pointer_type에서, sbyte, byte, short, ushort, int, uint, nint, nuint,long또는 ulong으로.

23.6.4 포인터 요소 액세스

[...] P[E]폼의 포인터 요소 액세스에서 Pvoid*이외의 포인터 형식의 식이어야 하며, Eint, uint, nint, nuint,long또는 ulong암시적으로 변환할 수 있는 식이어야 합니다.

23.6.7 포인터 산술 연산

안전하지 않은 컨텍스트에서 + 연산자와 연산자는 void*제외한 모든 포인터 형식의 값에 적용할 수 있습니다. 따라서 T*모든 포인터 형식에 대해 다음 연산자가 암시적으로 정의됩니다.

[...]
T* operator +(T* x, nint y);
T* operator +(T* x, nuint y);
T* operator +(nint x, T* y);
T* operator +(nuint x, T* y);
T* operator -(T* x, nint y);
T* operator -(T* x, nuint y);

포인터 형식 T*의 표현식 Pint, uint, nint, nuint,long, 또는 ulong형식의 표현식 N가 주어졌을 때, 표현식 P + NN + PP로 지정된 주소에 N * sizeof(T)를 더한 결과로 T* 형식의 포인터 값을 계산합니다. 마찬가지로 식 P – NP지정한 주소에서 N * sizeof(T) 빼서 발생하는 T* 형식의 포인터 값을 계산합니다.

다양한 고려 사항

주요 변경 내용

이 디자인의 주요 영향 중 하나는 System.IntPtrSystem.UIntPtr 일부 기본 제공 연산자(변환, 단항 및 이진)를 얻을 수 있다는 것입니다.
여기에는 checked 연산자가 포함됩니다. 즉, 해당 형식에서 다음 연산자는 오버플로될 때 예외를 던집니다.

  • IntPtr + int
  • IntPtr - int
  • IntPtr -> int
  • long -> IntPtr
  • void* -> IntPtr

메타데이터 인코딩

이 디자인은 System.Runtime.CompilerServices.NativeIntegerAttribute사용하지 않고 nintnuint 단순히 System.IntPtrSystem.UIntPtr내보낼 수 있음을 의미합니다.
마찬가지로 메타데이터 NativeIntegerAttribute 로드하는 경우 무시될 수 있습니다.