Dlaczego mam i ++; ja--; zaraz za sobą?

164

Patrzyłem na kod źródłowy nmap wydany w 1997 roku i zauważyłem ten fragment kodu, który wygląda mi trochę dziwnie:

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

Dlaczego miałbyś, i++;a potem i--;zaraz po sobie? ijest 0, a następnie i++zmienia isię w 1. Potem i--zwraca się ido 0.

Link do oryginalnego kodu źródłowego. Szukaj:

i++;
i--;

Czy ktoś może wyjaśnić, po co to jest?

DDiamond
źródło
25
Zapytaj autora .
DaBler
8
Sądzę, że były częścią kodu eksperymentalnego lub debugującego, którego autor zapomniał później usunąć.
Nate Eldredge
6
Powodem jest oczywiście dezorientacja, to jest jedyny cel :-) Istnieje niewielka szansa, że ​​to działa wokół jakiegoś błędu kompilatora w jakimś starożytnym kompilatorze, w takim przypadku powinien być komentarz podający ten powód.
gnasher729
18
@ RingØ: Dla zabawy wypróbowałem to z gcc 1.27, około 1988 roku, na godbolt: godbolt.org/z/yYyFrQ . (Nie działa z nowoczesnymi nagłówkami systemowymi, więc sam musiałem zadeklarować wszystkie standardowe funkcje biblioteki). Ale dzięki -Otemu rzeczywiście optymalizują te instrukcje.
Nate Eldredge
21
Oznacza to, że programista otrzymał wynagrodzenie za linię ...
TonyK

Odpowiedzi:

152

To był błąd. Te linie razem powodują, iże pozostają niezmienione, więc nie powinny tam być.

Powiązany artykuł, który wprowadził nmap, został opublikowany 1 września 1997 r. Jeśli spojrzysz na repozytorium SVN dla nmap na https://svn.nmap.org/nmap , wstępna wersja sprawdzona 10 lutego 1998 r. Nie zawiera następujących wierszy:

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

Jest to więc coś, co autor znalazł i naprawił między opublikowaniem początkowego kodu źródłowego nmap a początkowym zameldowaniem w SVN.

dbush
źródło
1
Hmm, na stronie brakuje też <pre>tagów wokół artykułu; Inspektor Chrome ujawnia, w jaki sposób prowadzi to do zniekształcania niektórych dokumentów podczas budowy DOM;)
Asteroids With Wings
4
To dezorientuje czytelników, co jest całkowicie niezamierzone. Powiedziałbym, że to oczywiście błąd. ;-)
Sergut
2
@sergut Wikipedia nie zgadza się z tobą, ale ten post na blogu zgadza się , a ja też jestem skłonny :-)
Toivo Säwén
4
Teraz, jeśli inie była to int, ale jakaś wymyślna klasa z przeciążeniem operatora, możliwe jest (choć mało prawdopodobne i ogólnie oznaka złych praktyk kodowania), że może to mieć pewne skutki uboczne. (Dotyczy tylko, jeśli był to oczywiście C ++.)
Darrel Hoffman
5
Być może warto zauważyć, że w niektórych kontekstach (IO zamapowane w pamięci) zmiana zmiennej może mieć efekty zewnętrzne.
nullromo
40

To jest bezużyteczne. Nie robi absolutnie nic.

Gdybym miał spekulować, to prawdopodobnie pozostałość kodu debugowania, który został użyty podczas programowania.

Zgaduję, że albo jeden i++albo i--został wprowadzony w jednej zmiany, a druga została wprowadzona w drugim.

Nie mam jednak sposobu, aby znaleźć punkt wprowadzenia, ponieważ nie było historii zmian między pierwszą wersją źródłową a pierwszą wersją SVN.

SS Anne
źródło
14
Myślę, że spekulacje na temat kodu debugowania są dokładne. Widziałem tak wiele różnych rodzajów kodu debugowania, aby uzyskać punkty przerwania tam, gdzie się ich spodziewasz.
Nathan Goings
9

Dla nieoptymalizującego kompilatora lub takiego, który rozpoznaje sprzętowe skutki uboczne, i ++; Sekwencja i spowoduje, że i zostanie odczytany z pamięci, a następnie ponownie zapisany, bez względu na ścieżkę przechodzącą przez pętlę for i zagnieżdżoną, jeśli.

W przetwarzaniu równoległym czasami wykorzystuje się włamania kompilatora, aby zapewnić, że sekwencja kodu używa własnych lokalnych kopii zmiennych zamiast kopii globalnych.

Ponieważ przykładem jest fragment kodu, nie można określić używanego kompilatora, oczekiwanego systemu operacyjnego / sprzętu ani tego, czy jest to sekwencja / funkcja kodu, którą można wykonać jako niezależny wątek.

W prostszych systemach tymczasowo zmusiłem zmiany zmiennych, aby korzystały z funkcji pułapki w środowisku debugowania. Gdyby tak było, autor mógł zapomnieć o usunięciu kodu po zakończeniu programowania.

Larry Fisher
źródło
1
to dlaczego po prostu nie uznać tego za niestabilne?
vsz
6
Deklaracja izmiennej lokalnej jest pokazana w powyższym kodzie i nie ma możliwości uzyskania dostępu do niej przez inny wątek w punkcie, w którym znajdują się i++; i--linie.
interjay
@vsz Raczej myślę, że ima na myśli, że musi być nieulotny. Nie zajmowałem się wątkami w C lub C ++, więc nie mam pojęcia, jak można to potraktować jako niestabilne i jak i++; i--by to stłumić.
Egor Hans,
lotny ma inne cele niż bezpieczeństwo wątków. Można go również użyć podczas debugowania, aby kompilator nie zoptymalizował go.
vsz
2

Zasugeruję sprawdzenie tylko zaktualizowanego kodu. Jeśli użyjesz (i = 2 + 1) zaraz po tym (i-1), to nie ma sensu. Wartość i pozostaje niezmieniona. Możesz spróbować za pomocą dowolnego kompilatora c lub c ++. lub nawet w innym języku jest to samo. Uruchom kod w kompilatorze, aby sprawdzić, czy się mylę, czy mam rację, i daj mi znać, jeśli udzielę złej odpowiedzi.

TripleM
źródło