Bagikan melalui


Operator penggeseran kanan tanpa tanda

Nota

Artikel ini adalah spesifikasi fitur. Spesifikasi berfungsi sebagai dokumen desain untuk fitur tersebut. Ini termasuk perubahan spesifikasi yang diusulkan, bersama dengan informasi yang diperlukan selama desain dan pengembangan fitur. Artikel ini diterbitkan sampai perubahan spesifikasi yang diusulkan diselesaikan dan dimasukkan dalam spesifikasi ECMA saat ini.

Mungkin ada beberapa perbedaan antara spesifikasi fitur dan implementasi yang selesai. Perbedaan tersebut diambil dalam catatan rapat desain bahasa (LDM) terkait.

Anda dapat mempelajari lebih lanjut tentang proses untuk mengadopsi speklet fitur ke dalam standar bahasa C# dalam artikel tentang spesifikasi .

Isu Utama: https://github.com/dotnet/csharplang/issues/4682

Ringkasan

Operator shift kanan tanpa tanda akan didukung oleh C# sebagai operator bawaan (untuk jenis integral primitif) dan sebagai operator yang didefinisikan pengguna.

Motivasi

Saat bekerja dengan nilai integral yang ditandatangani, tidak jarang Anda perlu menggeser bit ke kanan tanpa mereplikasi bit urutan tinggi pada setiap shift. Meskipun ini dapat dicapai untuk jenis integral primitif dengan operator shift reguler, diperlukan pengubahan tipe ke tipe unsigned sebelum operasi shift dan pengubahan tipe kembali setelah operasi tersebut. Dalam konteks antarmuka matematika generik yang akan diekspos pustaka, ini berpotensi lebih bermasalah karena tipe tersebut mungkin tidak memiliki padanan tanpa tanda yang ditentukan atau diketahui di muka oleh kode matematika generik, namun algoritma mungkin mengandalkan kemampuan untuk melakukan operasi pergeseran kanan tanpa tanda.

Desain terperinci

Operator dan tanda baca

Bagian §6.4.6 akan disesuaikan untuk menyertakan operator >>> - operator shift kanan yang tidak ditandatangani:

unsigned_right_shift
    : '>>>'
    ;

unsigned_right_shift_assignment
    : '>>>='
    ;

Tidak ada karakter apa pun (bahkan spasi kosong) yang diizinkan antara token dalam produksi unsigned_right_shift dan unsigned_right_shift_assignment. Produksi ini diperlakukan khusus untuk memungkinkan pemrosesan type_parameter_listyang benar.

Operator pergeseran

Bagian §12.11 akan disesuaikan untuk menyertakan operator >>> - operator shift kanan yang tidak ditandatangani:

Operator <<, >>, dan >>> digunakan untuk melakukan operasi pergeseran bit.

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

Untuk pengoperasian formulir x << count atau x >> count atau x >>> count, resolusi kelebihan beban operator biner (§12,4,5) diterapkan untuk memilih implementasi operator tertentu. Operand dikonversi ke tipe parameter dari operator yang dipilih, dan tipe hasilnya adalah tipe pengembalian dari operator.

Operator shift tanpa tanda akan mendukung set tanda tangan yang sama seperti yang didukung oleh operator shift bertanda dalam implementasi saat ini.

  • Geser ke kanan:

    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 >>> menggeser x ke kanan dengan jumlah bit yang dihitung seperti yang dijelaskan di bawah ini.

    Bit berurutan rendah x dibuang, bit yang tersisa digeser ke kanan, dan posisi bit kosong berurutan tinggi diatur ke nol.

Untuk operator yang telah ditentukan sebelumnya, jumlah bit yang akan digeser dihitung sebagai berikut:

  • Ketika jenis x adalah int atau uint, jumlah shift ditentukan oleh lima bit urutan rendah dari count. Dengan kata lain, jumlah shift dihitung dari count & 0x1F.
  • Ketika tipe x adalah long atau ulong, jumlah shift diberikan oleh enam bit dengan urutan terendah dari count. Dengan kata lain, jumlah shift dihitung dari count & 0x3F.

Jika jumlah shift yang dihasilkan adalah nol, operator shift hanya mengembalikan nilai x.

Operasi shift tidak pernah menyebabkan luapan dan menghasilkan hasil yang sama dalam konteks checked dan unchecked.

Operator penugasan

Bagian §12.21 akan disesuaikan untuk menyertakan unsigned_right_shift_assignment sebagai berikut:

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

Jenis integral

Tipe integral di bagian §8.3.6 akan disesuaikan untuk menyertakan informasi tentang operator . Poin yang relevan adalah sebagai berikut:

  • Untuk operator <<biner , >> dan >>>, operan kiri dikonversi ke jenis T, di mana T adalah yang pertama dari int, uint, long, dan ulong yang dapat sepenuhnya mewakili semua nilai operand yang mungkin. Operasi kemudian dilakukan menggunakan presisi jenis T, dan jenis dari hasilnya adalah T.

Ekspresi konstanta

Operator >>> akan ditambahkan ke kumpulan konstruksi yang diizinkan dalam ekspresi konstan pada §12,23.

Kelebihan beban operator

Operator >>> akan ditambahkan ke set operator biner yang dapat kelebihan beban pada §12.4.3.

Operator yang diangkat

Operator >>> akan ditambahkan ke dalam set operator biner yang mengizinkan bentuk yang diperluas pada §12.4.8.

Prioritas operator dan asosiasi

Bagian §12.4.2 akan disesuaikan untuk menambahkan operator >>> ke kategori "Shift" dan operator >>>= ke kategori "Penugasan dan ekspresi lambda".

Ambiguitas tata bahasa

Operator >>> tunduk pada ambiguitas tata bahasa yang sama yang dijelaskan pada §6,2,5 sebagai operator >> biasa.

Operator

Bagian §15.10 akan disesuaikan agar menyertakan operator >>>.

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

Operator biner

Tanda tangan operator >>> tunduk pada aturan yang sama dengan yang ada di §15.10.3 untuk tanda tangan operator >>.

Nama metadata

Bagian "I.10.3.2 Operator Biner" dari ECMA-335 sudah mencadangkan nama untuk operator shift kanan tak bertanda - op_UnsignedRightShift.

Pohon Ekspresi LINQ

Operator >>> tidak akan didukung di Pohon Ekspresi Linq karena semantik operator >>> yang telah ditentukan sebelumnya pada tipe bertanda tidak dapat diwakili secara akurat tanpa menambahkan konversi ke tipe tak bertanda dan kembali. Lihat https://github.com/dotnet/csharplang/blob/main/meetings/2022/LDM-2022-02-09.md#unsigned-right-shift-operator untuk informasi selengkapnya.

Pengikatan Dinamis

Sepertinya pengikatan dinamis menggunakan nilai enum System.Linq.Expressions.ExpressionType untuk mengomunikasikan jenis operator biner ke pengikat runtime. Karena kami tidak memiliki anggota yang secara khusus mewakili operator shift kanan tanpa tanda, pengikatan dinamis untuk operator >>> tidak akan didukung dan bagian pengikatan statis dan dinamis (§12.3) akan disesuaikan untuk mencerminkan perubahan ini.

Kekurangan

Alternatif

Pohon Ekspresi LINQ

Operator >>> akan didukung di Pohon Linq Expressioin.

  • Untuk operator yang ditentukan pengguna, simpul BinaryExpression yang menunjuk ke metode operator akan dibuat.
  • Untuk operator yang telah ditentukan sebelumnya
    • ketika operand pertama adalah jenis ansigned, simpul BinaryExpression akan dibuat.
    • ketika operand pertama adalah tipe bertanda, konversi untuk operand pertama ke tipe tidak bertanda akan ditambahkan, simpul BinaryExpression akan dibuat, dan konversi untuk mengembalikan hasil ke tipe bertanda akan ditambahkan.

Misalnya:

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

Resolution:

Ditolak, lihat https://github.com/dotnet/csharplang/blob/main/meetings/2022/LDM-2022-02-09.md#unsigned-right-shift-operator untuk informasi selengkapnya.

Pertanyaan yang belum terselesaikan

Rapat Desain

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