Mengapa saya ++; saya--; setelah satu sama lain?


164

Saya melihat kode sumber untuk nmap yang dirilis pada tahun 1997 dan saya perhatikan bagian kode ini yang terlihat sedikit aneh bagi saya:

int i=0, j=0,start,end;
char *expr = strdup(origexpr);
ports = safe_malloc(65536 * sizeof(short));
i++;                                         /* <<<<<< */
i--;                                         /* <<<<<< */
for(;j < exlen; j++) 
  if (expr[j] != ' ') expr[i++] = expr[j]; 
expr[i] = '\0';

Mengapa kamu memiliki i++;dan kemudian i--;setelah satu sama lain? iadalah 0, lalu i++beralih ike 1. Setelah itu, i--beralih ike 0.

Tautan ke kode sumber asli. Pencarian untuk:

i++;
i--;

Adakah yang bisa menjelaskan untuk apa ini?


25
Tanyakan penulis .
DaBler

8
Saya kira mereka adalah bagian dari beberapa kode eksperimental atau debugging, yang penulis lupa untuk menghapus sesudahnya.
Nate Eldredge

6
Alasannya jelas membingungkan Anda, itulah satu-satunya tujuan :-) Ada kemungkinan kecil ini bekerja di sekitar beberapa bug kompiler di beberapa kompiler kuno, dalam hal ini seharusnya ada komentar yang memberi tahu kami alasan ini.
gnasher729

18
@ RingØ: Untuk bersenang-senang saya mencobanya dengan gcc 1.27, sekitar tahun 1988, di godbolt: godbolt.org/z/yYyyFrQ . (Ini tidak bekerja dengan header sistem modern jadi saya harus mendeklarasikan semua fungsi perpustakaan standar sendiri.) Tetapi dengan -Oitu memang mengoptimalkan pernyataan-pernyataan itu.
Nate Eldredge

21
Itu berarti programmer dibayar oleh garis ...
TonyK

Jawaban:


152

Ini adalah bug. Garis-garis ini bersama-sama menghasilkan itidak berubah, jadi mereka seharusnya tidak ada di sana.

Artikel tertaut yang memperkenalkan nmap diterbitkan pada 1 September 1997. Jika Anda melihat repositori SVN untuk nmap di https://svn.nmap.org/nmap , revisi awal yang diperiksa pada 10 Februari 1998 tidak memiliki baris-baris berikut:

int i=0, j=0,start,end;
char *expr = strdup(origexpr);
char *mem = expr;

ports = safe_malloc(65536 * sizeof(short));
for(;j < exlen; j++) 
  if (expr[j] != ' ') expr[i++] = expr[j]; 
expr[i] = '\0';

Jadi ini adalah sesuatu yang penulis temukan dan perbaiki antara menerbitkan kode sumber nmap awal dan checkin awal ke SVN.


1
Hmm halaman itu juga tidak memiliki <pre>tag di sekitar artikel; Inspektur Chrome mengungkapkan bagaimana itu mengarah pada beberapa dokumen mangling selama konstruksi DOM;)
Asteroids With Wings

4
Ini membingungkan pembaca, yang sama sekali tidak disengaja. Saya akan mengatakan itu jelas bug. ;-)
sergut

2
@sergut Wikipedia tidak setuju dengan Anda, tetapi posting blog ini setuju , dan saya juga cenderung :-)
Toivo Säwén

4
Sekarang jika ibukan int tetapi beberapa kelas mewah dengan kelebihan operator, itu mungkin (meskipun tidak mungkin dan umumnya merupakan tanda praktik pengkodean yang buruk) bahwa ini dapat memiliki beberapa efek samping. (Hanya berlaku jika ini C ++ tentu saja.)
Darrel Hoffman

5
Mungkin perlu dicatat bahwa dalam beberapa konteks (IO yang dipetakan memori), mengubah variabel dapat memiliki efek eksternal.
nullromo

40

Percuma saja. Sama sekali tidak apa-apa.

Jika saya berspekulasi itu mungkin sisa-sisa kode debugging yang digunakan selama pengembangan.

Saya menduga salah satu i++atau i--diperkenalkan dalam satu perubahan dan yang lain diperkenalkan pada yang lain.

Saya tidak memiliki cara untuk menemukan titik pengantar, karena tidak ada riwayat revisi antara rilis sumber awal dan revisi SVN pertama.


14
Saya pikir spekulasi tentang kode debug akurat. Saya telah melihat begitu banyak jenis kode debug hanya untuk mendapatkan breakpoint di mana Anda mengharapkannya.
Nathan Goings

9

Untuk kompiler yang tidak mengoptimalkan, atau yang mengenali efek samping perangkat keras, i ++; urutan i-- akan menyebabkan saya dibaca dari memori, kemudian ditulis ulang, terlepas dari jalur yang diambil melalui for for dan bersarang jika.

Dalam pemrosesan paralel, kadang-kadang hack kompiler diambil untuk memastikan urutan kode menggunakan salinan variabel lokalnya sendiri daripada salinan global.

Karena contohnya adalah potongan kode, seseorang tidak dapat menentukan kompiler yang digunakan, sistem operasi / perangkat keras yang diharapkan, atau apakah ini dalam urutan kode / fungsi yang mungkin dapat dieksekusi sebagai utas independen.

Dalam sistem yang lebih sederhana, saya sementara telah memaksa perubahan pada variabel untuk menjalankan fitur perangkap di lingkungan debugging. Jika itu yang terjadi, penulis mungkin lupa menghapus kode ketika pengembangan selesai.


1
lalu mengapa tidak menyatakannya sebagai volatile?
vsz

6
Deklarasi isebagai variabel lokal ditunjukkan dalam kode di atas, dan tidak ada cara untuk dapat diakses oleh utas lain pada titik di mana i++; i--garis-garisnya.
interjay

@vsz Saya lebih suka dia maksudnya idipaksa menjadi non-volatile. Saya belum pernah berurusan dengan threading di C atau C ++, jadi saya tidak tahu bagaimana itu bisa dianggap volatile dan bagaimana i++; i--akan menekannya.
Egor Hans

volatile memiliki tujuan lain selain keamanan thread. Itu juga dapat digunakan saat debugging untuk memastikan kompiler tidak akan mengoptimalkannya.
vsz

2

Saya akan menyarankan Anda untuk memeriksa kode yang diperbarui saja. Jika Anda menggunakan (i = 2 +1) tepat setelah itu (i-1) itu tidak masuk akal. Nilai i tetap tidak berubah. Anda dapat mencobanya menggunakan kompiler c atau c ++. atau bahkan dalam bahasa lain sama saja. Jalankan kode di kompiler untuk melihat apakah saya salah atau benar, dan beri tahu saya jika saya memberikan jawaban yang salah.

Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.