Por que ter o i ++; Eu--; logo após o outro?

164

Eu estava olhando o código fonte do nmap lançado em 1997 e notei essa seção de código que me parece um pouco estranha:

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

Por que você teria i++;e i--;depois um do outro? ié 0, então i++vira ipara 1. Depois disso, i--vira ipara 0.

Link para o código fonte original. Procurar por:

i++;
i--;

Alguém pode explicar para que serve isso?

DDiamond
fonte
25
Pergunte ao autor .
DaBler 28/03
8
Eu acho que eles faziam parte de algum código experimental ou de depuração, que o autor esqueceu de remover posteriormente.
Nate Eldredge
6
Obviamente, o motivo é confundi-lo, esse é o único objetivo :-) Há uma pequena chance de que isso funcione em torno de algum bug do compilador em algum compilador antigo; nesse caso, deveria ter havido comentários nos dizendo esse motivo.
gnasher729 28/03
18
@ RingØ: Por diversão, tentei com o gcc 1.27, por volta de 1988, no godbolt: godbolt.org/z/yYyFrQ . (Ele não funciona com os cabeçalhos modernos do sistema, então eu mesmo tive que declarar todas as funções da biblioteca padrão.) Mas, com -Oisso, ele realmente otimiza essas instruções.
Nate Eldredge
21
Isso significa que o programador foi pago pela linha ...
TonyK em 30/03

Respostas:

152

Isso foi um bug. Essas linhas juntas resultam iinalteradas, portanto não deveriam estar lá.

O artigo vinculado que introduziu o nmap foi publicado em 1 de setembro de 1997. Se você olhar o repositório SVN para o nmap em https://svn.nmap.org/nmap , a revisão inicial registrada em 10 de fevereiro de 1998 não possui as seguintes linhas:

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

Portanto, isso é algo que o autor encontrou e corrigiu entre publicar o código-fonte inicial do nmap e o check-in inicial no SVN.

dbush
fonte
11
Hummm, nessa página também faltam <pre>tags no artigo; O inspetor do Chrome revela como isso leva a algum documento confundido durante a construção do DOM;)
Asteroids With Wings
4
Confunde os leitores, o que é completamente não intencional. Eu diria que é claramente um bug. ;-)
sergut 30/03
2
@sergut A Wikipedia não concorda com você, mas esta publicação do blog concorda e eu também :-)
Toivo Säwén
4
Agora, se inão fosse um int, mas alguma classe sofisticada com sobrecargas de operador, é possível (embora improvável e geralmente um sinal de práticas inadequadas de codificação) que isso possa ter alguns efeitos colaterais. (Somente se aplica se for C ++, é claro.)
Darrel Hoffman em
5
Talvez seja interessante notar que, em alguns contextos (E / S mapeadas na memória), a alteração de uma variável pode ter efeitos externos.
nullromo 30/03
40

É inútil. Não faz absolutamente nada.

Se eu fosse especular, provavelmente são os restos de algum código de depuração usado durante o desenvolvimento.

Eu estou supondo que um i++ou i--foi introduzido em uma mudança e o outro foi introduzido em outra.

Não tenho como encontrar o ponto de introdução, no entanto, porque não havia histórico de revisão entre o lançamento inicial da fonte e a primeira revisão do SVN.

SS Anne
fonte
14
Eu acho que a especulação sobre o código de depuração é precisa. Eu já vi tantos tipos diferentes de código de depuração apenas para obter pontos de interrupção onde você os espera.
Nathan Goings
9

Para um compilador que não otimiza ou que reconhece efeitos colaterais de hardware, o i ++; A sequência i-- faria com que eu fosse lido da memória e depois reescrito, independentemente do caminho percorrido pelo loop for e aninhado se.

No processamento paralelo, algumas vezes são executados hackers do compilador para garantir que uma sequência de código use suas próprias cópias locais de variáveis ​​em vez de cópias globais.

Como o exemplo é um trecho de código, não é possível determinar o compilador usado, o sistema operacional / hardware esperado, nem se isso está em uma sequência / função de código que pode ser executada como um encadeamento independente.

Em sistemas mais simples, forcei temporariamente alterações nas variáveis ​​para exercitar o recurso de interceptação em um ambiente de depuração. Se for esse o caso, o autor pode ter esquecido de remover o código quando o desenvolvimento foi concluído.

Larry Fisher
fonte
11
então por que não declarar isso como volátil?
vsz 31/03
6
A declaração icomo variável local é mostrada no código acima e não há como acessá-la por outro encadeamento no ponto em que as i++; i--linhas estão.
interjay 31/03
@ VSZ Eu prefiro pensar que ele quer dizer ié forçado a não ser volátil. No entanto, eu não lidei com o encadeamento em C ou C ++, por isso não faço ideia de como isso poderia ser tratado como volátil e como i++; i--suprimir isso.
Egor Hans
volátil tem outros propósitos além da segurança da rosca. Também pode ser usado durante a depuração para garantir que o compilador não o otimize.
vsz 6/04
2

Vou sugerir que você verifique apenas o código atualizado. Se você usar (i = 2 + 1) logo depois (i-1), isso não fará sentido. O valor de i permanece inalterado. Você pode experimentá-lo usando qualquer compilador c ou c ++. ou mesmo em qualquer outro idioma, é o mesmo. Execute o código no compilador para verificar se estou certo ou errado e me informe se estou dando uma resposta errada.

TripleM
fonte