Apa yang dimaksud dengan operator "->" di C ++?

8926

Setelah membaca Fitur Tersembunyi dan Sudut Gelap C ++ / STL aktif comp.lang.c++.moderated, saya benar-benar terkejut bahwa cuplikan berikut dikompilasi dan bekerja di Visual Studio 2008 dan G ++ 4.4.

Berikut kodenya:

#include <stdio.h>
int main()
{
    int x = 10;
    while (x --> 0) // x goes to 0
    {
        printf("%d ", x);
    }
}

Keluaran:

9 8 7 6 5 4 3 2 1 0

Saya berasumsi ini C, karena berfungsi di GCC juga. Di mana ini didefinisikan dalam standar, dan dari mana asalnya?

GManNickG
sumber
503
Atau bahkan jarak hanya tepat ... Saya tidak berpikir saya pernah melihat ruang antara variabel dan baik ++atau --sebelum ...
Matthew Scharley
1154
Operator "buka" ini dapat dikembalikan (0 <- x). Dan juga ada operator "lari ke" (0 <---- x). Ya ampun, hal terlucu yang pernah saya dengar tentang c ++ sintaks =) +1 untuk pertanyaan.
SadSido
233
Lucunya, meskipun interpretasinya sangat salah, ia menggambarkan apa yang kode lakukan dengan benar. :)
Noldorin
811
Bayangkan kemungkinan sintaksis baru: #define upto ++<, #define downto -->. Jika Anda merasa jahat, Anda dapat melakukan #define for while(dan #define do ) {(dan #define done ;}) dan menulis for x downto 0 do printf("%d\n", x) doneOh, kemanusiaan ...
Chris Lutz
98
Membuka kemungkinan cara pengkodean ekspresif yang sama sekali baru, layak mengorbankan beberapa kompiler peringatan untuk: bool CheckNegative (int x) {return x <0? benar salah ); }
ttt

Jawaban:

8604

-->bukan operator. Sebenarnya dua operator terpisah, --dan> .

Pengurangan kode kondisional x, sambil mengembalikan nilai xasli (tidak dikurangi), dan kemudian membandingkan nilai asli dengan 0menggunakan >operator.

Untuk lebih memahami, pernyataan itu dapat ditulis sebagai berikut:

while( (x--) > 0 )
Potatoswatter
sumber
262
Kemudian lagi, itu memang terlihat seperti semacam operator jangkauan dalam konteks itu.
Charles Salvia
109
Mengatakan bahwa x adalah post-decremented dan kemudian dibandingkan dengan 0 sama dengan mengatakan x dikurangi setelah dibandingkan dengan 0
Charles Salvia
8
Saya tidak berpikir itu sama. Saya pikir kata "maka" menyiratkan ada pesanan (setelah post decrementing, nilai x adalah satu kurang). Saya pikir orang dapat mengatakan "Anda memposting penurunan x dan kemudian membandingkan nilai lamanya dan 0 ..." untuk membuatnya lebih jelas. Tapi ini memang nitpicking. Kita semua tahu apa yang dimaksud.
Johannes Schaub - litb
38
Di Jawa juga dikompilasi :)
Steven Devijver
44
Nama untuk itu, @ Jay, adalah gaya pemrograman yang buruk :-) Ini dibuktikan dengan fakta bahwa pertanyaan itu ditanyakan sejak awal. Lebih masuk akal untuk mengikat operator secara teks dengan hal yang mereka operasikan daripada sesuatu yang tidak terkait, jadi while (x-- > 0)akan lebih tepat. Itu juga membuatnya lebih jelas apa yang terjadi (setidaknya dalam editor font tetap) yang berarti bahwa tanda kurung dalam jawaban ini tidak perlu.
paxdiablo
3132

Atau untuk sesuatu yang sama sekali berbeda ... xslide 0.

while (x --\
            \
             \
              \
               > 0)
     printf("%d ", x);

Tidak begitu matematis, tapi ... setiap gambar melukis seribu kata ...

tidak disinkronkan
sumber
216
@ mafutrct - Seperti yang saya ingat \ di C hanya menambahkan baris berikutnya seolah-olah tidak ada jeda baris. Di sini pada dasarnya tidak melakukan apa pun.
Hogan
2
@ mafu, karakter '\' memberi tahu kompiler bahwa baris saat ini berlanjut di baris berikutnya sehingga kompiler harus menggabungkan kedua baris dan mengkompilasinya sebagai satu. 'while (x -> 0)' akan berjalan sampai x sama dengan -1. Tapi, cara dia membuat lekukan membuatnya tampak seperti x meluncur ke nol. 'Sementara x slide ke 0 ...'
Felype
16
IIRC, K&R C memungkinkan spasi putih antara '-'s di operator decrement, dalam hal ini Anda bisa memiliki garis miring terbalik di tengahnya, yang akan terlihat lebih keren. :)
Jules
10
@ArnavBorborah ini adalah makna ekspresi yang lama why waste words when a picture does a better job, digunakan sebagai lelucon dalam konteks ini. (sebenarnya ada 2 kata kunci whiledan printf)
tidak disinkronkan
88
Ah ya, operator slide yang tidak jelas. Bagaimana saya bisa lupa!
demonkoryu
2378

Itu operator yang sangat rumit, bahkan ISO / IEC JTC1 (Joint Technical Committee 1) menempatkan deskripsinya dalam dua bagian berbeda dari Standar C ++.

Di samping bercanda, mereka adalah dua operator yang berbeda: --dan >dijelaskan masing-masing dalam §5.2.6 / 2 dan §5.9 dari Standar C ++ 03.

Kirill V. Lyadvinsky
sumber
1278

Ini setara dengan

while (x-- > 0)

x--(post decrement) setara dengan x = x-1itu, kode berubah menjadi:

while(x > 0) {
    x = x-1;
    // logic
}
x--;   // The post decrement done when x <= 0
Shubham
sumber
15
Ini tidak benar. Nilai x di dalam tubuh loop berbeda dalam kasus kedua. Pernyataan penugasan dalam contoh Anda harus di atas logika agar setara. Postfix - kurangi 1, tetapi perbandingan akan terjadi dengan nilai dari sebelum pengurangan.
uliwitness
4
@ Andrewitness Ini benar-benar setara. Akan salah jika awalan digunakan: 0 >-- xDalam hal xini dikurangi sebelum logika. Dalam postfix, logika dieksekusi sebelum penurunan dan dengan demikian kedua sampel setara. Jangan ragu untuk menuliskannya dalam Consoledan mengujinya.
Candleshark
12
Mereka masih belum setara. Setelah loop pertama, x adalah -1 (atau overflown jika tidak ditandatangani), setelah yang kedua, adalah 0. (Dengan anggapan bahwa x dimulai non-negatif, tidak ada loop yang memodifikasi x atau break atau ...)
Caesar
1
while(x=x-1,x+1 > 0)setara.
SS Anne
2
@ Shebham, Ini contoh penghitungnya: jika x dimulai dengan 0, di bawah loop asli ia akan keluar sebagai -1, dengan versi Anda itu akan tetap nol. Jadi mereka tidak setara.
Elliott
1210

x dapat mencapai nol lebih cepat di arah yang berlawanan:

int x = 10;

while( 0 <---- x )
{
   printf("%d ", x);
}

8 6 4 2

Anda dapat mengontrol kecepatan dengan panah!

int x = 100;

while( 0 <-------------------- x )
{
   printf("%d ", x);
}

90 80 70 60 50 40 30 20 10

;)

doc
sumber
6
sistem operasi mana, jenis keluaran ini yang dihasilkan, saya menggunakan ubuntu 12.04 karena saya memiliki pesan kesalahan
Bhuvanesh
74
Meskipun harus jelas, bagi semua orang yang baru mengenal C ++ membaca ini: jangan lakukan itu. Cukup gunakan penugasan augmented jika Anda harus menambah / mengurangi lebih dari satu.
Blimeo
263
Nol dengan "laser". while (0> - - - - - - - - - - ---------- x) ... output yang sama.
Samuel Danielson
4
@ phord, Anda yakin tidak dapat dikompilasi? -> coliru.stacked-crooked.com/a/5aa89a65e3a86c98
doc
18
@ doc Mengkompilasi dalam c ++, tetapi tidak dalam c.
phord
549

Nya

#include <stdio.h>
int main(void){
     int x = 10;

     while( x-- > 0 ){ // x goes to 0

       printf("%d ", x);
     }

     return 0;
}

Hanya ruang membuat hal-hal terlihat lucu, --mengurangi dan >membandingkan.

RageZ
sumber
432

Penggunaan -->memiliki relevansi historis. Pengurangan adalah (dan masih dalam beberapa kasus), lebih cepat daripada peningkatan pada arsitektur x86. Menggunakan -->menyarankan yang xakan 0, dan menarik bagi mereka yang memiliki latar belakang matematika.

Matt Joiner
sumber
479
Tidak sepenuhnya benar. Decrementing dan Incrementing mengambil jumlah waktu yang sama, manfaatnya adalah perbandingan ke nol sangat cepat dibandingkan dengan perbandingan versus variabel. Ini berlaku untuk banyak arsitektur, bukan hanya x86. Apa pun dengan instruksi JZ (melompat jika nol). Menyodok sekitar Anda dapat menemukan banyak loop "untuk" yang ditulis mundur untuk menghemat siklus pada perbandingan. Ini sangat cepat pada x86 karena tindakan decrementing variabel mengatur flag nol secara tepat, sehingga Anda bisa bercabang tanpa harus membandingkan variabel secara eksplisit.
burito
25
Nah, pengurangan menuju nol berarti Anda hanya perlu membandingkan dengan 0 per loop iterasi, sementara iterasi ke arah n berarti membandingkan dengan n setiap iterasi. Yang pertama cenderung lebih mudah (dan pada beberapa arsitektur, secara otomatis diuji setelah setiap operasi pendaftaran data).
Joey Adams
9
@ Burrito Meskipun saya tidak setuju, loop dikondisikan pada nilai-nilai non-nol umumnya diprediksi mendekati sempurna.
Duncan
14
Peningkatan dan penurunan sama cepatnya, mungkin pada semua platform (pasti pada x86). Perbedaannya adalah dalam menguji kondisi ujung lingkaran. Untuk melihat apakah penghitung telah mencapai nol praktis gratis - ketika Anda menurunkan nilai, flag nol diatur dalam prosesor dan untuk mendeteksi kondisi akhir Anda hanya perlu memeriksa bendera itu sedangkan ketika Anda menambahkan operasi perbandingan diperlukan sebelum kondisi akhir dapat dideteksi.
lego
7
Tentu saja, semua ini diperdebatkan belakangan ini, karena kompiler modern dapat membuat vektor dan membalikkan loop secara otomatis.
Lambda Fairy
367
while( x-- > 0 )

adalah bagaimana itu diuraikan.

Grumdrig
sumber
363

Benar-benar geek, tapi saya akan menggunakan ini:

#define as ;while

int main(int argc, char* argv[])
{
    int n = atoi(argv[1]);
    do printf("n is %d\n", n) as ( n --> 0);
    return 0;
}
Arrieta
sumber
17
@SAFX - Ini akan menjadi hieroglif sempurna dengan tanda kurung Mesir
mouviciel
1
Ini tidak dikompilasi. C bukan Pascal, di mana interiornya do ... whileadalah daftar pernyataan. Dalam C itu adalah sebuah blok, jadi harus demikian do { ... } while.
Marquis of Lorne
25
@ EJP itu mengkompilasi. Sintaksnya adalah do statement while ( expression ) ;. Karena itu, saya harap ini dipahami saya maksud contoh sebagai lelucon.
Escualo
321

Satu buku yang saya baca (saya tidak ingat buku mana) menyatakan: Kompiler mencoba mengurai ekspresi ke token terbesar dengan menggunakan aturan kiri kanan.

Dalam hal ini, ungkapan:

x-->0

Parsing ke token terbesar:

token 1: x
token 2: --
token 3: >
token 4: 0
conclude: x-- > 0

Aturan yang sama berlaku untuk ungkapan ini:

a-----b

Setelah diurai:

token 1: a
token 2: --
token 3: --
token 4: -
token 5: b
conclude: (a--)-- - b

Saya harap ini membantu untuk memahami ungkapan yang rumit ^^

NguyenDat
sumber
98
Penjelasan kedua Anda tidak benar. Kompilator akan melihat a-----bdan berpikir (a--)-- - b, yang tidak dikompilasi karena a--tidak mengembalikan nilai.
Tim Leaf
22
Selain itu, xdan --merupakan dua token yang terpisah.
Roland Illig
23
@ DoctorT: melewati lexer. hanya semantic pass yang mampu memunculkan kesalahan itu. jadi penjelasannya benar.
v.oddou
9
Selama Anda anggap -->sebagai operator (yang tersirat dengan pertanyaan yang diajukan), jawaban ini tidak membantu sama sekali - Anda akan berpikir bahwa token 2 adalah -->, bukan hanya --. Jika Anda tahu itu -->bukan operator, Anda mungkin tidak memiliki masalah dalam memahami kode dalam pertanyaan, jadi, kecuali Anda memiliki pertanyaan yang sama sekali berbeda, saya tidak begitu yakin bagaimana ini bisa berguna.
Bernhard Barker
4
Contoh @DoctorT bisa benar dengan asumsi bahwa aoperator post-decrement kelebihan beban, yang mengembalikan nilai. coliru.stacked-crooked.com/a/e1effc351ae79e9f
doc
275

Ini persis sama dengan

while (x--)
{
   printf("%d ", x);
}

untuk nomor non-negatif

Orang Baik
sumber
153
Bukankah ini seharusnya for(--x++;--x;++x--)?
Mateen Ulhaq
9
@DoctorT itulah yang unsignedbagi
Cole Johnson
12
@MateenUlhaq, itu salah menurut standar, ekspresi --x++memiliki perilaku yang tidak terdefinisi menurut §1.9.15
WorldSEnder
Jika menggunakan unsigned, itu akan digunakan%u
Cacahuete Frito
242

Bagaimanapun, kami memiliki operator "pergi ke" sekarang. "-->"mudah diingat sebagai arah, dan "sementara x pergi ke nol" artinya langsung.

Selain itu, ini sedikit lebih efisien daripada "for (x = 10; x > 0; x --)"pada beberapa platform.

Uji
sumber
17
Masuk ke cant benar selalu terutama ketika nilai x negatif.
Ganesh Gopalasubramanian
15
Versi lain tidak melakukan hal yang sama - dengan for (size_t x=10; x-->0; )tubuh loop dijalankan dengan 9,8, .., 0 sedangkan versi lainnya memiliki 10,9, .., 1. Sebaliknya, cukup sulit untuk keluar dari loop ke nol dengan variabel yang tidak ditandatangani.
Pete Kirkham
4
Saya pikir ini agak menyesatkan ... Kami tidak memiliki operator "ke" yang secara harfiah, karena kami membutuhkan operator lain ++>untuk melakukan pekerjaan tambahan.
tslmy
19
@Josh: sebenarnya, overflow memberikan perilaku yang tidak terdefinisi int, jadi bisa dengan mudah memakan anjing Anda xsampai nol jika mulai negatif.
SamB
3
Ini adalah ungkapan yang sangat penting bagi saya untuk alasan yang diberikan dalam comnmet oleh @PeteKirkham, karena saya sering perlu melakukan pengurangan loop atas jumlah yang tidak ditandai sampai ke sana 0. (Sebagai perbandingan, ungkapan menghilangkan tes untuk nol, seperti menulis while (n--)bukan untuk yang tidak ditandatangani n, tidak memberi Anda apa pun dan bagi saya sangat menghambat keterbacaan.) Ia juga memiliki properti menyenangkan yang Anda tentukan satu lebih dari indeks awal, yang biasanya Anda inginkan (misalnya, untuk loop di atas array Anda tentukan ukurannya). Saya juga suka -->tanpa ruang, karena ini membuat idiom mudah dikenali.
Marc van Leeuwen
221

Kode ini pertama kali membandingkan x dan 0 dan kemudian mengurangi x. (Juga disebutkan dalam jawaban pertama: Anda adalah post-decrementing x dan kemudian membandingkan x dan 0 dengan >operator.) Lihat output dari kode ini:

9 8 7 6 5 4 3 2 1 0

Kami sekarang pertama-tama membandingkan dan kemudian mengurangi dengan melihat 0 di output.

Jika kita ingin mengurangi pertama dan kemudian membandingkan, gunakan kode ini:

#include <stdio.h>
int main(void)
{
    int x = 10;

    while( --x> 0 ) // x goes to 0
    {
        printf("%d ", x);
    }
    return 0;
}

Output itu adalah:

9 8 7 6 5 4 3 2 1
SjB
sumber
177

Kompiler saya akan mencetak 9876543210 ketika saya menjalankan kode ini.

#include <iostream>
int main()
{
    int x = 10;

    while( x --> 0 ) // x goes to 0
    {
        std::cout << x;
    }
}

Seperti yang diharapkan. The while( x-- > 0 )sebenarnya berarti while( x > 0). The x--pasca decrements x.

while( x > 0 ) 
{
    x--;
    std::cout << x;
}

adalah cara berbeda untuk menulis hal yang sama.

Sangat menyenangkan bahwa aslinya terlihat seperti "sementara x pergi ke 0" sekalipun.

cool_me5000
sumber
4
Hasilnya hanya tidak terdefinisi ketika Anda menambah / mengurangi variabel yang sama lebih dari sekali dalam pernyataan yang sama. Itu tidak berlaku untuk situasi ini.
Tim Leaf
13
while( x-- > 0 ) actually means while( x > 0)- Saya tidak yakin apa yang ingin Anda katakan di sana, tetapi cara Anda mengatakannya menyiratkan --tidak memiliki arti apa pun, yang jelas sangat salah.
Bernhard Barker
Untuk mengarahkan titik pulang dari @Dukeling, jawaban ini tidak sama dengan pos asli. Di posting asli, xakan -1setelah itu meninggalkan loop, sedangkan di jawaban ini, xakan 0.
Mark Lakata
148

Ada ruang yang hilang antara --dan >. xadalah post decremented, yaitu decremented setelah memeriksa kondisi x>0 ?.

Mr. X
sumber
42
Ruang tidak hilang - C (++) mengabaikan spasi putih.
27
@ H2CO3 Ini tidak benar secara umum. Ada tempat di mana ruang putih harus digunakan untuk memisahkan token, misalnya dalam #define foo()versus #define foo ().
Jens
30
@ Jean Bagaimana dengan: "Ruang tidak hilang - C (++) mengabaikan ruang putih yang tidak perlu."?
Kevin P. Rice
139

--adalah penurunan operator dan >adalah lebih besar daripada operator.

Kedua operator diterapkan seperti satu -->.

muntoo
sumber
11
Mereka diterapkan sebagai 2 operator terpisah. Mereka hanya ditulis secara keliru sehingga terlihat seperti "satu".
underscore_d
129

Ini kombinasi dari dua operator. Pertama --adalah untuk mengurangi nilai, dan >untuk memeriksa apakah nilainya lebih besar dari operan kanan.

#include<stdio.h>

int main()
{
    int x = 10;

    while (x-- > 0)
        printf("%d ",x);

    return 0;
}

Outputnya adalah:

9 8 7 6 5 4 3 2 1 0            
Rajeev Das
sumber
122

Sebenarnya, xpost-decrementing dan dengan kondisi itu sedang diperiksa. Ini tidak -->, itu(x--) > 0

Catatan: nilai xdiubah setelah kondisi diperiksa, karena post-decrementing. Beberapa kasus serupa juga dapat terjadi, misalnya:

-->    x-->0
++>    x++>0
-->=   x-->=0
++>=   x++>=0
AndroidLearner
sumber
6
Kecuali bahwa ++> hampir tidak dapat digunakan untuk sementara waktu (). Operator "naik ke ..." akan menjadi ++ <, yang tidak terlihat bagus di mana pun. Operator -> adalah kebetulan yang membahagiakan.
Florian F
2
@BenLeggiero Itu bisa 'bekerja' dalam arti menghasilkan kode yang melakukan sesuatu (sementara membuat marah pembaca yang tidak suka kode pintar-palsu), tetapi semantiknya berbeda, karena penggunaan predecrement berarti akan melakukan iterasi yang lebih sedikit. Sebagai contoh yang dibuat-buat, itu tidak akan pernah menjalankan loop body jika xdimulai pada 1, tetapi while ( (x--) > 0 )akan. {sunting} Eric Lippert membahas keduanya dalam catatan rilis C # 4nya
underscore_d
120

C dan C ++ mematuhi aturan "maksimum mengunyah". Cara yang sama a --- b diterjemahkan ke (a--) - b, dalam kasus Anda x-->0diterjemahkan menjadi(x--)>0 .

Pada dasarnya aturan mengatakan bahwa dari kiri ke kanan, ekspresi dibentuk dengan mengambil karakter maksimum yang akan membentuk ekspresi yang valid.

Peter Mortensen
sumber
5
Itulah yang diasumsikan OP: bahwa "((a) ->)" adalah pengunyah maksimal. Ternyata asumsi asli OP salah: "->" bukan operator yang valid.
david
4
Juga dikenal sebagai penguraian serakah, jika saya ingat dengan benar.
Roy Tinker
1
@RoyTinker Pemindaian serakah . Parser tidak ada hubungannya dengan ini.
Marquis of Lorne
27

Kenapa semua komplikasinya?

Jawaban sederhana untuk pertanyaan awal adalah:

#include <stdio.h>
int main()
{
    int x = 10;
    while (x > 0) 
    {
        printf("%d ", x);
        x = x-1;
    }
}

Melakukan hal yang sama. Tidak mengatakan Anda harus melakukannya seperti ini, tetapi melakukan hal yang sama dan akan menjawab pertanyaan dalam satu posting.

Ini x--hanya singkatan untuk di atas, dan >hanya lebih besar dari normal operator. Bukan misteri besar!

Ada terlalu banyak orang membuat hal-hal sederhana menjadi rumit saat ini;)

Garry_G
sumber
17
Pertanyaan ini bukan tentang komplikasi, tetapi tentang ** Fitur Tersembunyi dan Sudut Gelap C ++ / STL **
pix
20
Program di sini memberikan output yang berbeda dari yang asli karena x di sini dikurangi setelah printf. Itu menunjukkan dengan baik bagaimana "jawaban sederhana" biasanya salah.
Öö Tiib
2
The OP's way: 9 8 7 6 5 4 3 2 1 0danThe Garry_G way: 10 9 8 7 6 5 4 3 2 1
Anthony
2
Itu tidak melakukan hal yang sama. Pindahkan x=x-1sebelum printfAnda maka Anda dapat mengatakan "itu melakukan hal yang sama".
CITBL
26

Dengan cara konvensional kita akan mendefinisikan suatu kondisi dalam whilekurung loop ()dan kondisi terminating di dalam kurung {}, tetapi--> mendefinisikan keduanya sekaligus.

Sebagai contoh:

int abc(void)
{
    int a = 5
    while((a--) > 0) // Decrement and comparison both at once
    {
        // Code
    }
}

Ini mengurangi adan menjalankan loop sementara alebih besar dari0 .

Secara konvensional, itu akan seperti:

int abc(void)
{
    int a = 5;
    while(a > 0)
    {
        a--;
        // Code
    }
    a--;
}

Kedua cara, kami melakukan hal yang sama dan mencapai tujuan yang sama.

Zohaib Ejaz
sumber
5
Ini salah. Kode dalam pertanyaan tidak: 'test-write-execute' (tes pertama, tulis nilai baru, jalankan loop), contoh Anda adalah 'test-execute-write'.
v010dya
@ v010dya Memperbaiki jawabannya, sekarang test-write-executeseperti dalam pertanyaan, terima kasih telah menunjukkan!
Kotauskas
@VladislavToncharov Hasil edit Anda masih salah. Lihat milikku.
SS Anne
8

(x --> 0) cara (x-- > 0)

  1. kamu bisa menggunakan (x -->)
    output -: 9 8 7 6 5 4 3 2 1 0

  2. Anda dapat menggunakan (-- x > 0) itu berarti(--x > 0)
    output -: 9 8 7 6 5 4 3 2 1

  3. kamu bisa menggunakan
(--\
    \
     x > 0)

output -: 9 8 7 6 5 4 3 2 1

  1. kamu bisa menggunakan
(\
  \
   x --> 0)

output -: 9 8 7 6 5 4 3 2 1 0

  1. kamu bisa menggunakan
(\
  \
   x --> 0
          \
           \
            )

output -: 9 8 7 6 5 4 3 2 1 0

  1. Anda juga bisa menggunakannya
(
 x 
  --> 
      0
       )

output -: 9 8 7 6 5 4 3 2 1 0

Anda juga dapat mencoba banyak metode untuk menjalankan perintah ini dengan sukses

Kalana
sumber