¿Qué es el operador "->" en C / C ++?

Despues de leer Funciones ocultas y esquinas oscuras de C ++ / STL on comp.lang.c++.moderated, Me sorprendió por completo que el siguiente fragmento se compilara y funcionara tanto en Visual Studio 2008 como en G ++ 4.4.

Aquí está el código:

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

Salida:

9 8 7 6 5 4 3 2 1 0

Asumiría que esto es C, ya que también funciona en GCC. ¿Dónde se define esto en la norma y de dónde viene?

preguntado Oct 29 '09, 03:10

26 Respuestas

--> no es un operador. De hecho, son dos operadores separados, -- y >.

Decrementos del código del condicional x, mientras regresa xvalor original (no decrementado), y luego compara el valor original con 0 usando el > operador.

Para comprender mejor, la declaración podría escribirse de la siguiente manera:

while( (x--) > 0 )

Respondido el 23 de diciembre de 18 a las 15:12

O por algo completamente diferente ... x se desliza a 0.

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

No tan matemático, pero ... cada imagen pinta mil palabras ...

Respondido el 08 de enero de 20 a las 22:01

Es un operador muy complicado, así que incluso ISO / IEC JTC1 (Comité Técnico Conjunto 1) colocó su descripción en dos partes diferentes del estándar C ++.

Bromas aparte, son dos operadores diferentes: -- y > descritos respectivamente en §5.2.6 / 2 y §5.9 del estándar C ++ 03.

Respondido 02 Oct 19, 09:10

x puede ir a cero incluso más rápido en la dirección opuesta:

int x = 10;

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

8 6 4 2

¡Puedes controlar la velocidad con una flecha!

int x = 100;

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

90 80 70 60 50 40 30 20 10

;)

Respondido 11 Oct 17, 03:10

"¡Puedes controlar la velocidad con una flecha!". Gracias, lo odio. - DeusXMachina

Una respuesta adecuada a la pregunta. - paradocslover

Es equivalente a

while (x-- > 0)

x-- (decremento posterior) es equivalente a x = x-1 entonces, el código se transforma en:

while(x > 0) {
    x = x-1;
    // logic
}
x--;   // The post decrement done when x <= 0

Respondido 25 Abr '20, 11:04

Es

#include <stdio.h>

int main(void) {
  int x = 10;
  while (x-- > 0) { // x goes to 0
    printf("%d ", x);
  }
  return 0;
}

Solo el espacio hace que las cosas se vean divertidas -- decrementos y > compara.

Respondido 20 Oct 20, 04:10

El uso de --> tiene relevancia histórica. Reducir fue (y sigue siendo en algunos casos) más rápido que incrementar en la arquitectura x86. Utilizando --> sugiere que x va a 0, y atrae a aquellos con antecedentes matemáticos.

respondido 18 nov., 09:12

No es exactamente cierto. Decrementar e Incrementar toman la misma cantidad de tiempo, el beneficio de esto es que la comparación con cero es muy rápida en comparación con la comparación con una variable. Esto es cierto para muchas arquitecturas, no solo para x86. Cualquier cosa con una instrucción JZ (saltar si es cero). Buscando, puede encontrar muchos bucles "for" que están escritos al revés para guardar ciclos en la comparación. Esto es particularmente rápido en x86, ya que el acto de disminuir la variable establece el indicador cero de manera adecuada, por lo que luego puede bifurcar sin tener que comparar explícitamente la variable. - burito

Bueno, disminuir hacia cero significa que solo tiene que comparar con 0 por iteración de ciclo, mientras que iterar hacia n significa comparar con n cada iteración. El primero tiende a ser más fácil (y en algunas arquitecturas, se prueba automáticamente después de cada operación de registro de datos). - joey adams

Esto sería mejor como nota a pie de página en otra respuesta o comentario; claramente no explica qué --> significa, que es lo que se preguntó. - Bernardo Barker

En x86 ASM, el LOOP <address> disminuye el ECX registrarse, luego salta a <address> a menos que la disminución de ECX resultó en cero. Disminuir el contador de bucle hacia cero permite al compilador generar un solo LOOP instrucción, mientras que incrementar o contar a otros valores requiere instrucciones separadas INC / DEC / ADD / SUB, comparar y salto condicional. Los compiladores modernos a menudo pueden convertir otros bucles en un counter --> 0 bucle si el valor de counter no se utiliza en el bucle. - marca k cowan

Continuando con mi comentario anterior: MOV ECX, value, @start:, <code>, LOOP @start es un equivalente de ASM x86 para counter = value - 1; while (counter --> 0) { <code>; }. Tenga en cuenta que vomitará si value es inicialmente cero, por lo que se necesita una verificación adicional antes del ciclo. - marca k cowan

Totalmente geek, pero usaré esto:

#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;
}

Respondido el 03 de diciembre de 11 a las 02:12

Sé que se ve muy bien, pero me temo que es engañoso. La razón por la que está escribiendo C ++ en lugar de lenguaje de máquina es porque desea transmitir su intención al siguiente tipo que lea su código. Esta construcción viola el principio de mínima sorpresa. Es un "peligro de tropiezo" mental. - StevePoling

while( x-- > 0 )

así es como se analiza.

respondido 19 nov., 09:19

Un libro que leí (no recuerdo correctamente qué libro) decía: Los compiladores intentan analizar las expresiones hasta el token más grande utilizando la regla de izquierda a derecha.

En este caso, la expresión:

x-->0

Analiza a tokens más grandes:

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

La misma regla se aplica a esta expresión:

a-----b

Después de analizar:

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

Espero que esto ayude a entender la complicada expresión ^^

Respondido 23 Abr '15, 10:04

Esto es exactamente lo mismo que

while (x--)

respondido 12 mar '21, 12:03

¿No debería ser esto? for(--x++;--x;++x--)? - mateen ulhaq

@DoctorT eso es lo que unsigned es para - cole johnson

while (x --> 0) is no lo mismo que while (x--) if x tiene un tipo firmado, el primer bucle no se ejecuta en absoluto si x tiene un valor negativo, pero el segundo se repite muchas veces hasta que alcanza un comportamiento indefinido cuando x alcances INT_MIN. - chqrlie

De todos modos, ahora tenemos un operador "va a". "-->" es fácil de recordar como una dirección, y "mientras x va a cero" tiene sentido recto.

Además, es un poco más eficiente que "for (x = 10; x > 0; x --)" en algunas plataformas.

Respondido 28 Feb 13, 17:02

No puede ser cierto siempre, especialmente cuando el valor de x es negativo. - Ganesh Gopalasubramanian

La otra versión no hace lo mismo, con for (size_t x=10; x-->0; ) el cuerpo del bucle se ejecuta con 9,8, .., 0 mientras que la otra versión tiene 10,9, .., 1. De lo contrario, es bastante complicado salir de un bucle hasta cero con una variable sin firmar. - Pete Kirkham

Creo que esto es un poco engañoso ... No tenemos un operador "va a" literalmente, ya que necesitamos otro ++> para hacer el trabajo incremental. - tslmy

@Josh: en realidad, el desbordamiento da un comportamiento indefinido para int, por lo que podría comerse a su perro tan fácilmente como tomar x a cero si comienza negativo. - SamB

Este es un modismo muy importante para mí por la razón dada en el comnmet por @PeteKirkham, ya que a menudo necesito hacer bucles decrecientes sobre cantidades sin firmar hasta 0. (A modo de comparación, el modismo de omitir pruebas para cero, como escribir while (n--) en lugar de sin firmar n, no le compra nada y para mí dificulta enormemente la legibilidad). También tiene la propiedad agradable que usted especifica uno mas que el índice inicial, que suele ser lo que desea (por ejemplo, para un bucle sobre una matriz, especifica su tamaño). también me gusta --> sin espacio, ya que esto hace que el idioma sea fácil de reconocer. - Marc van Leeuwen

Este código primero compara x y 0 y luego disminuye x. (También se dice en la primera respuesta: está disminuyendo xy luego comparando x y 0 con el > operador.) Vea el resultado de este código:

9 8 7 6 5 4 3 2 1 0

Ahora primero comparamos y luego disminuimos al ver 0 en la salida.

Si primero queremos disminuir y luego comparar, use este código:

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

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

Esa salida es:

9 8 7 6 5 4 3 2 1

Respondido el 03 de enero de 16 a las 17:01

--x> 0 ¿Es esa x en una nave espacial que se dirige hacia 0 (la luna)? - H-005

Mi compilador imprimirá 9876543210 cuando ejecuto este código.

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

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

Como se esperaba. La while( x-- > 0 ) en realidad significa while( x > 0). Las x-- post decrementos x.

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

es una forma diferente de escribir lo mismo.

Sin embargo, es bueno que el original se vea como "mientras que x va a 0".

Respondido 30 Abr '15, 23:04

El resultado solo está indefinido cuando aumenta / disminuye la misma variable más de una vez en la misma declaración. No se aplica a esta situación. - hoja de tim

while( x-- > 0 ) actually means while( x > 0) - No estoy seguro de lo que estaba tratando de decir allí, pero la forma en que lo expresó implica la -- no tiene ningún significado, lo que obviamente está muy mal. - Bernardo Barker

Para llevar el punto a casa desde @Dukeling, esta respuesta es no es el mismo como la publicación original. En la publicación original, x se mostrarán -1 después de que deja el bucle, mientras que en esta respuesta, x se mostrarán 0. - marca lakata

Falta un espacio entre -- y >. x es post decrementado, es decir, decrementado después de verificar la condición x>0 ?.

respondido 22 nov., 10:19

No falta el espacio: C (++) ignora los espacios en blanco. - usuario529758

@ H2CO3 Esto no es cierto en general. Hay lugares donde se deben usar espacios en blanco para separar tokens, por ejemplo, en #define foo() frente a #define foo (). - Jens

@Jens ¿Qué tal: "No falta el espacio - C (++) ignora los espacios en blanco innecesarios"? - Kevin P. Arroz

-- es la decremento operador y > es la mas grande que operador.

Los dos operadores se aplican como uno solo como -->.

Respondido 29 Oct 11, 22:10

Ellos son aplicado como los 2 operadores separados que son. Son solo escrito engañosamente para parecer "uno solo". - subrayado_d

Es una combinación de dos operadores. Primero -- es para disminuir el valor, y > sirve para comprobar si el valor es mayor que el operando de la derecha.

#include<stdio.h>

int main()
{
    int x = 10;

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

    return 0;
}

La salida será:

9 8 7 6 5 4 3 2 1 0            

Respondido 30 Abr '15, 23:04

En realidad, x es post-decremento y con esa condición se está comprobando. Que no es -->, Es (x--) > 0

Nota: valor de x se cambia después de que se verifica la condición, ya que se post-decrementa. También pueden ocurrir algunos casos similares, por ejemplo:

-->    x-->0
++>    x++>0
-->=   x-->=0
++>=   x++>=0

Respondido 12 Abr '14, 10:04

Excepto que ++> difícilmente se puede usar en un tiempo (). Un operador "sube a ..." sería ++ <, que no se ve tan bien en ningún lado. El operador -> es una feliz coincidencia. - Florian F

@BenLeggiero Eso podría 'funcionar' en el sentido de generar código que hace algo (mientras enfurece a los lectores a quienes no les gusta el código falso), pero la semántica es diferente, ya que su uso de predecremento significa que ejecutará una iteración menos. Como ejemplo artificial, nunca ejecutaría el cuerpo del bucle si x comenzó en 1, pero while ( (x--) > 0 ) haría. {edit} Eric Lippert cubrió ambos en sus notas de la versión de C # 4: blogs.msdn.microsoft.com/ericlippert/2010/04/01/… - subrayado_d

C y C + + obedezca la regla de "masticar máximo". De la misma manera que a --- b se traduce a (a--) - b, en tu caso x-->0 traduce a (x--)>0.

Lo que la regla dice esencialmente es que yendo de izquierda a derecha, las expresiones se forman tomando el máximo de caracteres que formarán una expresión válida.

Respondido 12 Abr '14, 10:04

Que es lo que asumió el OP: que "((a) ->)" era el munch máximo. Resulta que la suposición original del OP era incorrecta: "->" no es un operador válido máximo. - David

También conocido como análisis codicioso, si no recuerdo mal. - Roy Tinker

@RoyTinker Codicioso exploración. El analizador no tiene nada que ver con esto. - user207421

¿Por qué tanta complicación?

La respuesta simple a la pregunta original es simplemente:

#include <stdio.h>

int main()
{
    int x = 10;
    while (x > 0)
    {
        printf("%d ", x);
        x = x-1;
    }
}

Hace la misma cosa. No estoy diciendo que debas hacerlo así, pero hace lo mismo y habría respondido la pregunta en una publicación.

El sistema x-- es solo una abreviatura de lo anterior, y > es solo un normal mayor que operator. ¡No es un gran misterio!

Hay demasiada gente que complica las cosas simples hoy en día;)

Respondido 28 Oct 20, 23:10

Esta pregunta no se trata de complicaciones, sino de ** Características ocultas y esquinas oscuras de C ++ / STL ** - pix

El programa aquí da una salida diferente a la original porque x aquí se reduce después de printf. Eso demuestra bien cómo las "respuestas simples" suelen ser incorrectas. - Öö Tiib

The OP's way: 9 8 7 6 5 4 3 2 1 0 y The Garry_G way: 10 9 8 7 6 5 4 3 2 1 - Antonio

No hace lo mismo. Mueve tu x=x-1 antes printf entonces puedes decir "hace lo mismo". - CITBL

Forma convencional en la que definimos la condición en el paréntesis de bucle while "()"y condición de terminación dentro de las llaves"{}", pero esto -- & > es una forma en que uno define todo a la vez. Por ejemplo:

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

Dice, decrementar a y ejecuta el ciclo hasta el momento a es mayor que 0

De otra manera debería haber sido como:

int abc() {
    int a = 5;
    while(a > 0) {
        a = a -1 // Decrement inside loop
        // Code
    }
}

En ambos sentidos, hacemos lo mismo y logramos los mismos objetivos.

Respondido el 30 de diciembre de 20 a las 17:12

Esto es incorrecto. El código en la pregunta hace: 'prueba-escritura-ejecución' (prueba primero, escribe un nuevo valor, ejecuta el ciclo), tu ejemplo es 'prueba-ejecución-escritura'. - v010dya

@ v010dya Se corrigió la respuesta, ahora es test-write-execute como en la pregunta, gracias por señalar! - Kotauskas

@SSAnne Tu edición sigue siendo incorrecta. La a-- después de un tiempo no debería estar allí. - Stefan Fabián

En ambos sentidos, hacemos lo mismo y logramos los mismos objetivos. Realmente no: ambos bucles se repiten 5 veces, pero el valor final de a después de que el ciclo se completa es -1 en el primer caso y 0 en el segundo. - chqrlie

(x --> 0) significa (x-- > 0).

  1. Puede usar el (x -->)
    Output: 9 8 7 6 5 4 3 2 1 0
  1. Puede usar el (-- x > 0) Es grosero (--x > 0)
    Output: 9 8 7 6 5 4 3 2 1
  1. Puede usar el
(--\
    \
     x > 0)

Output: 9 8 7 6 5 4 3 2 1

  1. Puede usar el
(\
  \
   x --> 0)

Output: 9 8 7 6 5 4 3 2 1 0

  1. Puede usar el
(\
  \
   x --> 0
          \
           \
            )

Output: 9 8 7 6 5 4 3 2 1 0

  1. Se puede utilizar también
(
 x 
  --> 
      0
       )

Output: 9 8 7 6 5 4 3 2 1 0

Del mismo modo, puede probar muchos métodos para ejecutar este comando con éxito.

Respondido 28 Oct 20, 22:10

char sep = '\n'  /1\
; int i = 68    /1  \
; while (i  ---      1\
                       \
                       /1/1/1                               /1\
                                                            /1\
                                                            /1\
                                                            /1\
                                                            /1\
                            /           1\
                           /            1 \
                          /             1  \
                         /              1   \
                         /1            /1    \
                          /1          /1      \
                           /1        /1        /1/1> 0) std::cout \
                              <<i<<                               sep;

Para números más grandes, C ++ 20 presenta algunas características de bucle más avanzadas. Primero en atrapar i podemos construir un loop-de-loop inverso y desviarlo hacia el std::ostream. Sin embargo, la velocidad de i está definido por la implementación, por lo que podemos usar el nuevo operador de velocidad C ++ 20 <<i<< para acelerarlo. También debemos atraparlo construyendo un muro, si no lo hacemos, i abandona el ámbito y su desreferencia provoca un comportamiento indefinido. Para especificar el separador, podemos usar:

 std::cout \
           sep

y ahí tenemos un ciclo for de 67 a 1.

Respondido el 23 de enero de 21 a las 07:01

Aquí -- es el operador de decremento posterior unario.

 while (x-- > 0) // x goes to 0
 {
     printf("%d ", x);
 }
  • Al principio, la condición se evaluará como (x > 0) // 10 > 0
  • Ahora que la condición es verdadera, entrará en el ciclo con un valor decrementado x-- // x = 9
  • Por eso el primer valor impreso es 9
  • Y así. En el último bucle x=1, entonces la condición es verdadera. Según el operador unario, el valor cambió a x = 0 en el momento de la impresión.
  • Ahora, x = 0, que evalúa la condición (x > 0 ) como falso y el mientras salidas de bucle.

Respondido 28 Oct 20, 22:10

Este planteamiento de « --> no es un operador en absoluto. Tenemos un operador como ->, pero no como -->. Es solo una interpretación incorrecta de while(x-- >0) lo que simplemente significa que x tiene el operador de decremento posterior y este ciclo se ejecutará hasta que sea mayor que cero.

Otra forma sencilla de escribir este código sería while(x--). Las mientras El bucle se detendrá siempre que obtenga una condición falsa y aquí solo hay un caso, es decir, 0. Entonces se detendrá cuando el valor x se reduzca a cero.

Respondido 28 Oct 20, 22:10

--> no es un operador, es la yuxtaposición de -- (post-decremento) y > (mayor que la comparación).

El bucle se verá más familiar como:

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

Este bucle es un modismo clásico para enumerar valores entre 10 (el límite superior excluido) y 0 el límite inferior incluido, útil para iterar sobre los elementos de una matriz desde el último hasta el primero.

El valor inicial 10 es el número total de iteraciones (por ejemplo, la longitud de la matriz) y uno más el primer valor utilizado dentro del ciclo. La 0 es el último valor de x dentro del bucle, de ahí el comentario x va a 0.

Tenga en cuenta que el valor de x después de que el ciclo se completa es -1.

Tenga en cuenta también que este bucle operará el mismo manera si x tiene un tipo sin firmar como size_t, que es una gran ventaja sobre la alternativa ingenua for (i = length-1; i >= 0; i--).

Por esta razón, soy un fanático de esta sorprendente sintaxis: while (x --> 0). Encuentro este modismo llamativo y elegante, al igual que for (;;) contra: while (1) (que parece confusamente similar a while (l)). También funciona en otros lenguajes cuya sintaxis está inspirada en C: C ++, Objective-C, java, javascript, C # por nombrar algunos.

respondido 12 mar '21, 17:03

Me pregunto por qué esta respuesta se convirtió automáticamente en un wiki de la comunidad ... - chqrlie

Tiene suficiente reputación para saber: a) esta es una pregunta wiki de la comunidad, por lo que todas las respuestas son wiki de la comunidad, yb) esta respuesta es solo una duplicación de la plétora de respuestas existentes, en una pregunta de una década. - GManNickG

@GManNickG: No era consciente de la conexión implícita entre preguntas y respuestas para el estado de la comunidad wiki, no todo es obvio, incluso después de miles de horas contribuyendo al sitio, pero no soy demasiado mayor para aprender. Respecto a la respuesta parafraseando otras respuestas, solo quería subrayar un aspecto que no se abordan en otras respuestas y que no es obvio para los lectores ocasionales: while (n-- > 0) es perfecto para unsigned tipos. - chqrlie

Lo suficientemente justo. ¿Quizás un comentario sobre una respuesta existente sea más apropiado? - GManNickG

@GManNickG: Comenté sobre diferencias firmadas / no firmadas en Buena personarespuesta. Mi respuesta ilustra cómo este ciclo es simple y apropiado para enumerar los miembros de la matriz. Ninguna de las respuestas aborda esto tampoco ... veamos si otros moderadores consideran oportuno eliminarlo. - chqrlie

No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas or haz tu propia pregunta.