¿Por qué tengo i ++; yo--; ¿uno tras otro?

164

Estaba mirando el código fuente de nmap que se lanzó en 1997 y noté esta sección de código que me parece un poco extraña:

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 qué lo harías i++;y luego i--;uno después del otro? ies 0, luego se i++vuelve ihacia 1. Después de eso, se i--vuelve ihacia 0.

Enlace al código fuente original. Buscar:

i++;
i--;

¿Alguien puede explicar para qué es esto?

DDiamond
fuente
25
Pregúntale al autor .
DaBler
8
Supongo que formaron parte de algún código experimental o de depuración, que el autor olvidó eliminar después.
Nate Eldredge
66
La razón obviamente es confundirlo, ese es el único propósito :-) Hay una pequeña posibilidad de que esto funcione alrededor de algún error del compilador en algún compilador antiguo, en ese caso debería haber un comentario que nos diga esta razón.
gnasher729
18
@ RingØ: por diversión lo probé con gcc 1.27, alrededor de 1988, en godbolt: godbolt.org/z/yYyFrQ . (No funciona con los encabezados de los sistemas modernos, así que tuve que declarar todas las funciones de la biblioteca estándar por mí mismo). Pero con -Oeso, efectivamente, optimizo esas declaraciones.
Nate Eldredge
21
Significa que el programador fue pagado por la línea ...
TonyK

Respuestas:

152

Esto fue un error. Estas líneas juntas ino cambian, por lo que no deberían haber estado allí.

El artículo vinculado que introdujo nmap se publicó el 1 de septiembre de 1997. Si mira el repositorio SVN de nmap en https://svn.nmap.org/nmap , la revisión inicial registrada el 10 de febrero de 1998 no tiene esas líneas:

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

Entonces, esto es algo que el autor encontró y solucionó entre la publicación del código fuente inicial de nmap y el registro inicial en SVN.

dbush
fuente
1
Hmm, a esa página también le faltan <pre>etiquetas en el artículo; El inspector de Chrome revela cómo eso lleva a algunos documentos destrozados durante la construcción del DOM;)
Asteroides con alas
44
Confunde a los lectores, lo cual es completamente involuntario. Yo diría que es claramente un error. ;-)
sergut
2
@sergut Wikipedia no está de acuerdo con usted, pero esta publicación de blog sí, y también me inclino a :-)
Toivo Säwén
44
Ahora, si ino se tratara de una clase int pero elegante con sobrecargas del operador, es posible (aunque poco probable y generalmente un signo de malas prácticas de codificación) que esto podría tener algunos efectos secundarios. (Solo se aplica si esto era C ++, por supuesto).
Darrel Hoffman
55
Quizás valga la pena señalar que en algunos contextos (IO mapeada en memoria), cambiar una variable puede tener efectos externos.
nullromo
40

Es inutil. No hace absolutamente nada.

Si tuviera que especular, probablemente sean los restos de algún código de depuración que se utilizó durante el desarrollo.

Supongo que cualquiera de i++o i--se introdujo en un cambio y el otro se introdujo en otro.

Sin embargo, no tengo forma de encontrar el punto de introducción, porque no había un historial de revisión entre la versión de origen inicial y la primera revisión de SVN.

SS Anne
fuente
14
Creo que la especulación sobre el código de depuración es precisa. He visto tantos tipos diferentes de código de depuración solo para obtener puntos de interrupción donde los espera.
Nathan Goings
9

Para un compilador no optimizador, o uno que reconoce los efectos secundarios del hardware, el i ++; i-- la secuencia haría que i fuera leída de la memoria, luego reescrita, independientemente de la ruta tomada a través del bucle for y anidada if.

En el procesamiento paralelo, a veces se toman hacks del compilador para garantizar que una secuencia de código use sus propias copias locales de variables en lugar de copias globales.

Como el ejemplo es un fragmento de código, no se puede determinar el compilador utilizado, el sistema operativo / hardware esperado, ni si está en una secuencia / función de código que se puede ejecutar como un hilo independiente.

En sistemas más simples, forcé temporalmente cambios en las variables para ejercer la función de captura en un entorno de depuración. Si ese fuera el caso, el autor puede haber olvidado eliminar el código cuando se completó el desarrollo.

Larry Fisher
fuente
1
entonces, ¿por qué no simplemente declararlo como volátil?
vsz
66
La declaración de icomo una variable local se muestra en el código anterior, y no hay forma de que otro hilo pueda acceder a ella en el punto donde están las i++; i--líneas.
Interjay
@vsz Más bien creo que quiere decir que ise ve obligado a ser no volátil. Sin embargo, no he tratado con subprocesos en C o C ++, por lo que no tengo idea de cómo podría tratarse como volátil y cómo i++; i--podría suprimir eso.
Egor Hans
volátil tiene otros fines además de la seguridad del hilo. También se puede usar durante la depuración para garantizar que el compilador no lo optimice.
vsz
2

Le sugeriré que verifique solo el código actualizado. Si usa (i = 2 + 1) justo después de eso (i-1) eso no tiene sentido. El valor de i permanece sin cambios. Puedes probarlo usando cualquier compilador de c o c ++. o incluso en cualquier otro idioma es lo mismo. Ejecute el código en el compilador para ver si estoy equivocado o correcto, y avíseme si estoy dando una respuesta incorrecta.

TripleM
fuente