Udostępnij za pośrednictwem


Operator niepodpisanego przesunięcia w prawo

Notatka

Ten artykuł jest specyfikacją funkcji. Specyfikacja służy jako dokument projektowy dla funkcji. Zawiera proponowane zmiany specyfikacji wraz z informacjami wymaganymi podczas projektowania i opracowywania funkcji. Te artykuły są publikowane do momentu sfinalizowania proponowanych zmian specyfikacji i włączenia ich do obecnej specyfikacji ECMA.

Mogą wystąpić pewne rozbieżności między specyfikacją funkcji a ukończoną implementacją. Te różnice są przechwytywane w odpowiednich spotkania projektowego języka (LDM).

Więcej informacji na temat procesu wdrażania specyfikacji funkcji można znaleźć w standardzie języka C# w artykule dotyczącym specyfikacji .

Streszczenie

Operator bezznakowego przesunięcia w prawo będzie obsługiwany przez C# jako operator zdefiniowany przez użytkownika i jako wbudowany operator dla typów całkowitych.

Motywacja

Podczas pracy z podpisaną wartością całkowitą nie jest rzadkością, że trzeba przesuwać bity w prawo bez replikowania bitu o wysokiej kolejności na każdym przesunięciu. Chociaż można to osiągnąć dla określonych typów pierwotnych całkowitych za pomocą standardowego operatora przesunięcia, konieczne jest rzutowanie na typ niepodpisany przed operacją przesunięcia, a następnie rzutowanie z powrotem po jej wykonaniu. W kontekście ogólnych interfejsów matematycznych, które biblioteki planują udostępnić, może to być bardziej problematyczne, ponieważ typ może nie mieć zdefiniowanego lub wcześniej znanego niepodpisanego odpowiednika w ogólnym kodzie matematycznym, a algorytm może polegać na możliwości wykonania niepodpisanej operacji przesunięcia w prawo.

Szczegółowy projekt

Operatory i znaki interpunkcyjne

Sekcja §6.4.6 zostanie dostosowana w celu uwzględnienia operatora >>> - operatora niepodpisanego przesunięcia prawego:

unsigned_right_shift
    : '>>>'
    ;

unsigned_right_shift_assignment
    : '>>>='
    ;

Żadne znaki dowolnego rodzaju (nawet białe znaki) nie są dozwolone między tokenami w konstrukcjach unsigned_right_shift i unsigned_right_shift_assignment. Te produkcje są traktowane w szczególny sposób, aby umożliwić poprawną obsługę list typu_parametrów .

Operatory przesunięcia

Sekcja §12.11 zostanie dostosowana w celu uwzględnienia operatora >>> - operatora niepodpisanego przesunięcia prawego:

Operatory <<, >> i >>> służą do wykonywania operacji przesunięcia bitów.

shift_expression
    : additive_expression
    | shift_expression '<<' additive_expression
    | shift_expression right_shift additive_expression
    | shift_expression unsigned_right_shift additive_expression
    ;

W przypadku operacji formularza x << count lub x >> count lub x >>> countfunkcja rozpoznawania przeciążenia operatora binarnego (§12.4.5) jest stosowana w celu wybrania określonej implementacji operatora. Operandy są konwertowane na typy parametrów wybranego operatora, a typ wyniku jest zwracanym typem operatora.

Wstępnie zdefiniowane niepodpisane operatory przesunięcia będą obsługiwać ten sam zestaw podpisów, które obecnie obsługują wstępnie zdefiniowane operatory przesunięcia w bieżącej implementacji.

  • Shift w prawo:

    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);
    

    Operator >>> zmienia x w prawo przez kilka bitów obliczonych zgodnie z poniższym opisem.

    Bity o niskiej kolejności x są odrzucane, pozostałe bity są przesunięte w prawo, a puste pozycje bitów o wysokiej kolejności są ustawione na zero.

W przypadku wstępnie zdefiniowanych operatorów liczba bitów do przesunięcia jest obliczana w następujący sposób:

  • Gdy typ x jest int lub uint, liczba przesunięć jest określana przez pięć najmłodszych bitów count. Innymi słowy, liczba zmian jest obliczana z count & 0x1F.
  • Gdy typ x to long lub ulong, liczba przesunięć jest podawana przez sześć najmniej znaczących bitów count. Innymi słowy, liczba zmian jest obliczana z count & 0x3F.

Jeśli wynikowa liczba zmian wynosi zero, operatory przesunięcia po prostu zwracają wartość x.

Operacje przesunięcia nigdy nie powodują przepełnienia i generują te same wyniki w kontekstach checked i unchecked.

Operatory przypisania

Sekcja §12.21 zostanie skorygowana w celu uwzględnienia unsigned_right_shift_assignment w następujący sposób:

assignment_operator
    : '='
    | '+='
    | '-='
    | '*='
    | '/='
    | '%='
    | '&='
    | '|='
    | '^='
    | '<<='
    | right_shift_assignment
    | unsigned_right_shift_assignment
    ;

Typy całkowite

Sekcja dotyczącą typów całkowitych §8.3.6 zostanie dostosowana, aby uwzględnić informacje o operatorze >>>. Istotny punkt jest następujący:

  • W przypadku operatorów <<binarnych , >> i >>> lewy operand jest konwertowany na typ T, gdzie T jest pierwszym z int, uint, longi ulong, które mogą w pełni reprezentować wszystkie możliwe wartości operandu. Następnie operacja jest wykonywana przy użyciu precyzji typu T, a typ wyniku jest T.

Wyrażenia stałe

Operator >>> zostanie dodany do zestawu konstrukcji dozwolonych w wyrażeniach stałych w §12.23.

Przeciążenie operatora

Operator >>> zostanie dodany do zestawu przeciążalnych operatorów binarnych w §12.4.3.

Operatory zniesione

Operator >>> zostanie dodany do zestawu operatorów binarnych pozwalających na podniesioną formę w §12.4.8.

Pierwszeństwo operatora i asocjacyjność

Sekcja §12.4.2 zostanie dostosowana w celu dodania operatora >>> do kategorii "Shift" i operatora >>>= do kategorii "Przypisanie i wyrażenie lambda".

Niejednoznaczności gramatyczne

Operator >>> podlega tym samym niejednoznacznościom gramatycznym opisanym w §6.2.5 jako zwykły operator >>.

Operatorów

Sekcja §15.10 zostanie dostosowana w celu uwzględnienia operatora >>>.

overloadable_binary_operator
    : '+'   | '-'   | '*'   | '/'   | '%'   | '&'   | '|'   | '^'   | '<<'
    | right_shift | unsigned_right_shift | '=='  | '!='  | '>'   | '<'   | '>='  | '<='
    ;

Operatory binarne

Podpis operatora >>> podlega tym samym zasadom, co zasady w §15.10.3 dla podpisu operatora >>.

Nazwa metadanych

Sekcja "I.10.3.2 Operatory binarne" ECMA-335 już zarezerwowała nazwę operatora niepodpisanego przesunięcia prawego — op_UnsignedRightShift.

Drzewa wyrażeń Linq

Operator >>> nie będzie obsługiwany w drzewach wyrażeń Linq, ponieważ semantyka wstępnie zdefiniowanych operatorów >>> w typach podpisanych nie może być dokładnie reprezentowana bez dodawania konwersji do niepodpisanego typu i z powrotem. Aby uzyskać więcej informacji, zobacz https://github.com/dotnet/csharplang/blob/main/meetings/2022/LDM-2022-02-09.md#unsigned-right-shift-operator.

Powiązanie dynamiczne

Wygląda na to, że powiązanie dynamiczne używa wartości z wyliczenia System.Linq.Expressions.ExpressionType, aby przekazać typ operatora binarnego do łącznika środowiska uruchomieniowego. Ponieważ nie mamy elementu członkowskiego reprezentującego niepodpisany operator przesunięcia prawego, powiązanie dynamiczne dla operatora >>> nie będzie obsługiwane, a powiązanie statyczne i dynamiczne (§12.3) zostanie dostosowane, aby to odzwierciedlić.

Wady

Alternatywy

Drzewa wyrażeń Linq

Operator >>> będzie obsługiwany w drzewach wyrażeń Linq.

  • W przypadku operatora zdefiniowanego przez użytkownika zostanie utworzony węzeł BinaryExpression wskazujący metodę operatora.
  • Dla wstępnie zdefiniowanych operatorów
    • gdy pierwszy operand jest typem bez znaku, zostanie utworzony węzeł typu BinaryExpression.
    • gdy pierwszy operand jest typem ze znakiem, zostanie dodana konwersja pierwszego operandu na typ bez znaku, zostanie utworzony węzeł BinaryExpression i zostanie dodana konwersja wyniku z powrotem do typu ze znakiem.

Na przykład:

Expression<System.Func<int, int, int>> z = (x, y) => x >>> y; // (x, y) => Convert((Convert(x, UInt32) >> y), Int32)

Resolution:

Odrzucono, zobacz https://github.com/dotnet/csharplang/blob/main/meetings/2022/LDM-2022-02-09.md#unsigned-right-shift-operator, aby uzyskać więcej informacji.

Nierozwiązane pytania

Spotkania projektowe

https://github.com/dotnet/csharplang/blob/main/meetings/2022/LDM-2022-02-09.md