Compartilhar via


Operador de deslocamento para a direita sem sinal

Nota

Este artigo é uma especificação de recurso. A especificação serve como o documento de design para o recurso. Ele inclui alterações de especificação propostas, juntamente com as informações necessárias durante o design e o desenvolvimento do recurso. Esses artigos são publicados até que as alterações de especificação propostas sejam finalizadas e incorporadas na especificação ECMA atual.

Pode haver algumas discrepâncias entre a especificação do recurso e a implementação concluída. Essas diferenças são capturadas nas notas pertinentes da reunião de design de idioma (LDM).

Você pode saber mais sobre o processo de adoção de speclets de recursos no padrão de linguagem C# no artigo sobre as especificações de .

Resumo

Um operador de deslocamento para a direita sem sinal terá suporte do C# como um operador interno (para tipos integrais primitivos) e como um operador definido pelo usuário.

Motivação

Ao trabalhar com valor integral assinado, não é incomum que você precise deslocar bits para a direita sem replicar o bit de ordem alta em cada turno. Embora isso possa ser obtido para tipos integrais primitivos com um operador de deslocamento regular, é necessária uma conversão para um tipo sem sinal antes da operação de deslocamento e uma conversão de retorno após isso. Dentro do contexto das interfaces matemáticas genéricas que as bibliotecas estão planejando expor, isso pode ser mais problemático, pois o tipo talvez não tenha uma contraparte sem assinatura definida ou conhecida previamente pelo código matemático genérico, mas um algoritmo pode depender da capacidade de executar uma operação de deslocamento à direita sem assinatura.

Design detalhado

Operadores e pontuadores

A seção §6.4.6 será ajustada para incluir o operador >>> – o operador de deslocamento para a direita sem assinatura:

unsigned_right_shift
    : '>>>'
    ;

unsigned_right_shift_assignment
    : '>>>='
    ;

Nenhum tipo de caractere (nem mesmo espaço em branco) é permitido entre os tokens nas produções unsigned_right_shift e unsigned_right_shift_assignment. Essas produções são tratadas especialmente para habilitar o tratamento correto de type_parameter_lists.

Operadores shift

A seção §12.11 será ajustada para incluir o operador >>> – o operador de deslocamento para a direita sem assinatura:

Os operadores <<, >> e >>> são usados para executar operações de alteração de bits.

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

Para uma operação do formulário x << count ou x >> count ou x >>> count, a resolução de sobrecarga do operador binário (§12.4.5) é aplicada para selecionar uma implementação de operador específica. Os operandos são convertidos nos tipos de parâmetro do operador selecionado e o tipo do resultado é o tipo de retorno do operador.

Os operadores de turno sem assinatura predefinidos darão suporte ao mesmo conjunto de assinaturas que os operadores de turno assinados predefinidos dão suporte hoje na implementação atual.

  • Deslocar à direita:

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

    O operador >>> desloca x para a direita por um número de bits calculado, como descrito abaixo.

    Os bits de baixa ordem de x são descartados, os bits restantes são deslocados para a direita e as posições de bits vazias de ordem alta são definidas como zero.

Para os operadores predefinidos, o número de bits a serem deslocados é computado da seguinte maneira:

  • Quando o tipo de x é int ou uint, a contagem de turnos é fornecida pelos cinco bits de ordem inferior de count. Em outras palavras, a contagem de turnos é computada de count & 0x1F.
  • Quando o tipo de x é long ou ulong, a contagem de turnos é fornecida pelos seis bits de ordem inferior de count. Em outras palavras, a contagem de turnos é computada de count & 0x3F.

Se a contagem de turnos resultante for zero, os operadores de deslocamento simplesmente retornarão o valor de x.

As operações de deslocamento nunca causam estouros e produzem os mesmos resultados nos contextos checked e unchecked.

Operadores de atribuição

A seção §12.21 será ajustada para incluir unsigned_right_shift_assignment da seguinte maneira:

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

Tipos integrais

A seção dos tipos integrais §8.3.6 será ajustada para incluir informações sobre o operador >>>. O tópico relevante é o seguinte:

  • Para os operadores binários <<, >> e >>>, o operando esquerdo é convertido para o tipo T, onde T é o primeiro de int, uint, longe ulong que pode representar totalmente todos os valores possíveis do operando. Em seguida, a operação é executada usando a precisão do tipo Te o tipo do resultado é T.

Expressões constantes

O operador >>> será adicionado ao conjunto de constructos permitidos em expressões constantes em §12.23.

Sobrecarga de operador

O operador >>> será adicionado ao conjunto de operadores binários sobrecarregados em §12.4.3.

Operadores suspensos

O operador >>> será adicionado ao conjunto de operadores binários que permitem um formulário em §12.4.8.

Precedência e associatividade do operador

A seção §12.4.2 será ajustada para adicionar os operadores >>> à categoria "Deslocamento" e >>>= à categoria "Atribuição e expressão lambda".

Ambiguidades gramaticais

O operador >>> está sujeito às mesmas ambiguidades gramaticais descritas em §6.2.5 como um operador de >> regular.

Operadores

A seção §15.10 será ajustada para incluir o operador >>>.

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

Operadores binários

A assinatura de um operador de está sujeita às mesmas regras que as de para a assinatura de um operador de .

Nome dos metadados

A seção "Operadores binários I.10.3.2" do ECMA-335 já reservou o nome para um operador de deslocamento à direita sem assinatura - op_UnsignedRightShift.

Árvores de expressão Linq

O operador >>> não será suportado nas Árvores de Expressão Linq, pois a semântica dos operadores >>> predefinidos em tipos assinados não pode ser representada com precisão sem adicionar conversões para um tipo sem assinatura e vice-versa. Consulte https://github.com/dotnet/csharplang/blob/main/meetings/2022/LDM-2022-02-09.md#unsigned-right-shift-operator para obter mais informações.

Ligação dinâmica

Parece que a associação dinâmica usa valores da enumeração System.Linq.Expressions.ExpressionType para comunicar o tipo de operador binário ao associador de runtime. Como não temos um membro que represente especificamente um operador de deslocamento à direita sem sinal, não haverá suporte para associação dinâmica para o operador >>> e a seção sobre associação estática e dinâmica (§12.3) será ajustada para refletir isso.

Inconvenientes

Alternativas

Árvores de expressão Linq

O operador >>> receberá suporte nas Árvores de Expressões do Linq.

  • Para um operador definido pelo usuário, será criado um nó BinaryExpression apontando para o método do operador.
  • Para operadores predefinidos
    • quando o primeiro operando é do tipo não assinado, um nó BinaryExpression será criado.
    • quando o primeiro operando for um tipo assinado, uma conversão para o primeiro operando para um tipo não assinado será adicionada, um nó de expressão binária será criado e a conversão do resultado de volta para o tipo assinado será adicionada.

Por exemplo:

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

Resolution:

Rejeitado, consulte https://github.com/dotnet/csharplang/blob/main/meetings/2022/LDM-2022-02-09.md#unsigned-right-shift-operator para obter mais informações.

Perguntas não resolvidas

Reuniões de design

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