stringtranslate.com

operador de coma

En los lenguajes de programación C y C++ , el operador coma (representado por el token , ) es un operador binario que evalúa su primer operando y descarta el resultado, y luego evalúa el segundo operando y devuelve este valor (y tipo); hay un punto de secuencia entre estas evaluaciones.

El uso del token de coma como operador es distinto de su uso en llamadas y definiciones de funciones, declaraciones de variables, declaraciones de enumeración y construcciones similares, donde actúa como un separador .

Sintaxis

El operador de coma separa expresiones (que tienen valor) de una manera análoga a cómo el punto y coma termina las declaraciones, y las secuencias de expresiones se encierran entre paréntesis de manera análoga a cómo las secuencias de declaraciones se encierran entre llaves: [1] (a, b, c) es una secuencia de expresiones, separadas por comas, que se evalúa hasta la última expresión c, mientras que {a; b; c;}es una secuencia de declaraciones y no se evalúa hasta ningún valor. Una coma solo puede aparecer entre dos expresiones ( expresiones separadas por comas ), a diferencia del punto y coma, que aparece al final de una declaración (que no es de bloque), los puntos y coma terminan declaraciones.

El operador de coma tiene la precedencia más baja de cualquier operador de C y actúa como un punto de secuencia . En una combinación de comas y punto y coma, los puntos y coma tienen menor prioridad que las comas, ya que los puntos y comas separan las declaraciones, pero las comas aparecen dentro de las declaraciones, lo que concuerda con su uso como puntuación ordinaria: a, b; c, dse agrupa como (a, b); (c, d)porque son dos declaraciones separadas.

El operador de coma ha quedado obsoleto en expresiones de subíndice (a partir de C++20 ); [2] para reducir la confusión y abrir la posibilidad futura de reutilizar la sintaxis para la indexación de matrices multidimensionales. En C++23operator[] , se agregó la capacidad de sobrecargar con múltiples argumentos, lo que hace que las expresiones de coma sin paréntesis sean inutilizables en los subíndices. [3] El operador de coma todavía se puede utilizar y no está obsoleto en este contexto si la expresión de coma está entre paréntesis (como en a[(b,c)]).

Ejemplos

En este ejemplo, el comportamiento diferente entre la segunda y la tercera línea se debe a que el operador de coma tiene menor prioridad que la asignación. El último ejemplo también difiere ya que la expresión de retorno debe evaluarse completamente antes de que la función pueda regresar.

/** * Las comas actúan como separadores en esta línea, no como operadores. * Resultados: a=1, b=2, c=3, i=0 */ int a = 1 , b = 2 , c = 3 , i = 0 ;    /** * Asigna el valor de b a i. * Las comas actúan como separadores en la primera línea y como operadores en la segunda línea. * Resultados: a=1, b=2, c=3, i=2 */ int a = 1 , b = 2 , c = 3 ; int yo = ( a , b ); /** * Asigna el valor de a a i. * Equivalente a: int i = a; intb; * Las comas actúan como separadores en ambas líneas. * Las llaves en la segunda línea evitan la redeclaración de variables en el mismo bloque, * lo que causaría un error de compilación. * A la segunda b declarada no se le asigna ningún valor inicial. * Resultados: a=1, b=2, c=3, i=1 */ int a = 1 , b = 2 , c = 3 ; { int yo = a , b ; }                    /** * Aumenta el valor de a en 2, luego asigna el valor de la operación resultante a + b a i. * Las comas actúan como separadores en la primera línea y como operadores en la segunda línea. * Resultados: a=3, b=2, c=3, i=5 */ int a = 1 , b = 2 , c = 3 ; int i = ( a += 2 , a + b ); /** * Aumenta el valor de a en 2, luego almacena el valor de a en i y descarta los valores * no utilizados de la operación resultante a + b. * Equivalente a: (i = (a += 2)), a + b; * Las comas actúan como separadores en la primera línea y como operador en la tercera línea. * Resultados: a=3, b=2, c=3, i=3 */ int a = 1 , b = 2 , c = 3 ; int yo ; yo = a += 2 , a + b ;                       /** * Asigna el valor de a a i. * Las comas actúan como separadores en ambas líneas. * Las llaves en la segunda línea evitan la redeclaración de variables en el mismo bloque, * lo que causaría un error de compilación. * Los segundos b y c declarados no reciben ningún valor inicial. * Resultados: a=1, b=2, c=3, i=1 */ int a = 1 , b = 2 , c = 3 ; { int yo = a , b , c ; }          /** * Las comas actúan como separadores en la primera línea y como operadores en la segunda línea. * Asigna el valor de c a i, descartando los valores a y b no utilizados. * Resultados: a=1, b=2, c=3, i=3 */ int a = 1 , b = 2 , c = 3 ; int yo = ( a , b , c );        /** * Devuelve 6, no 4, ya que los puntos de secuencia del operador de coma que siguen a la palabra clave * return se consideran una expresión única que se evalúa como rvalue de la subexpresión final * c=6. * Las comas actúan como operadores en esta línea. */ devolver a = 4 , b = 5 , c = 6 ;   /** * Devuelve 3, no 1, por el mismo motivo que el ejemplo anterior. * Las comas actúan como operadores en esta línea. */ devolver 1 , 2 , 3 ;   /** * Devuelve 3, no 1, por el mismo motivo que el anterior. Este ejemplo funciona como lo hace * porque return es una palabra clave, no una llamada a función. Aunque los compiladores * permitirán la construcción return(value), los paréntesis son sólo relativos al "valor" * y no tienen ningún efecto especial en la palabra clave return. * Return simplemente obtiene una expresión y aquí la expresión es "(1), 2, 3". * Las comas actúan como operadores en esta línea. */ retorno ( 1 ), 2 , 3 ;  

Usos

El operador de coma tiene casos de uso relativamente limitados. Debido a que descarta su primer operando, generalmente solo es útil cuando el primer operando tiene efectos secundarios deseables que deben secuenciarse antes del segundo operando. Además, debido a que rara vez se usa fuera de modismos específicos y se confunde fácilmente con otras comas o el punto y coma, es potencialmente confuso y propenso a errores. Sin embargo, hay ciertas circunstancias en las que se usa comúnmente, especialmente en bucles for y SFINAE . [4] Para sistemas integrados que pueden tener capacidades de depuración limitadas, el operador de coma se puede usar en combinación con una macro para anular sin problemas una llamada de función, para insertar código justo antes de la llamada de función.

Para bucles

El uso más común es permitir múltiples declaraciones de asignación sin usar una declaración de bloque, principalmente en las expresiones de inicialización e incremento de un bucle for . Este es el único uso idiomático en la programación elemental en C. En el siguiente ejemplo, el orden de los inicializadores del bucle es importante:

void rev ( char * s , size_t len ) { char * primero ; for ( primero = s , s += len ; s >= primero ; -- s ) { putchar ( * s ); } }                    

Una solución alternativa a este problema en otros lenguajes es la asignación paralela , que permite que se produzcan múltiples asignaciones dentro de una sola declaración y también utiliza una coma, aunque con diferente sintaxis y semántica. Esto se usa en Go en su bucle for análogo. [5]

Fuera de los inicializadores de bucle for (que tienen un uso especial de punto y coma), se puede usar la coma en lugar de un punto y coma, particularmente cuando las declaraciones en cuestión funcionan de manera similar a un incremento de bucle (por ejemplo, al final de un bucle while):

++ p , ++ q ; ++ p ; ++ q ;  

macros

La coma se puede utilizar en macros de preprocesador para realizar múltiples operaciones en el espacio de una única expresión sintáctica.

Un uso común es proporcionar mensajes de error personalizados en aserciones fallidas. Esto se hace pasando una lista de expresiones entre paréntesis a la assertmacro, donde la primera expresión es una cadena de error y la segunda expresión es la condición que se afirma. La assertmacro genera su argumento palabra por palabra en caso de error de aserción. Lo siguiente es un ejemplo:

#incluir <stdio.h> #incluir <afirmar.h>  int principal ( vacío ) { int i ; for ( i = 0 ; i <= 9 ; i ++ ) { afirmar ( ( "¡i es demasiado grande!" , i <= 4 ) ); printf ( "i = %i \n " , i ); } devolver 0 ; }                        

Producción:

yo = 0yo = 1yo = 2yo = 3yo = 4afirmar: afirmar.c:6: test_assert: Afirmación `( "¡Soy demasiado grande!", I <= 4 )' falló.Abortado

Sin embargo, la macro de afirmación generalmente está deshabilitada en el código de producción, así que úsela solo con fines de depuración.

Condición

La coma se puede usar dentro de una condición (de if, while, do while o for) para permitir cálculos auxiliares, en particular llamar a una función y usar el resultado, con alcance de bloque :

if ( y = f ( x ), y > x ) { ... // declaraciones que involucran x e y }         

Existe un modismo similar en Go , donde la sintaxis de la declaración if permite explícitamente una declaración opcional. [6]

Retorno complejo

La coma se puede utilizar en declaraciones de retorno, para asignar a una variable global o parámetro de salida (pasado por referencia). Este modismo sugiere que las asignaciones son parte de la declaración, en lugar de asignaciones auxiliares en un bloque que termina con la declaración real. Por ejemplo, al configurar un número de error global:

si ( fallo ) regresa ( errno = EINVAL , -1 );      

Esto se puede escribir de manera más detallada como:

si ( fallo ) { errno = EINVAL ; devolver -1 ; }       

evitar un bloqueo

Por motivos de brevedad, se puede utilizar la coma para evitar un bloque y las llaves asociadas, como en:

si ( x == 1 ) y = 2 , z = 3 ;         
si ( x == 1 ) y = 2 , z = 3 ;         

en lugar de:

si ( x == 1 ) { y = 2 ; z = 3 ;}         
si ( x == 1 ) { y = 2 ; z = 3 ; }          

Otros idiomas

En los lenguajes de programación OCaml y Ruby , se utiliza el punto y coma (";") para este propósito. JavaScript [7] y Perl [8] utilizan el operador de coma de la misma manera que lo hace C/C++. En Java , la coma es un separador que se utiliza para separar elementos de una lista en varios contextos. [9] No es un operador y no evalúa hasta el último elemento de la lista. [10]

Ver también

Referencias

  1. ^ "Operador de coma". Documentos de desarrollo de Microsoft . Archivado desde el original el 2 de agosto de 2019 . Consultado el 1 de agosto de 2019 . Dos expresiones separadas por una coma se evalúan de izquierda a derecha. El operando izquierdo siempre se evalúa y todos los efectos secundarios se completan antes de evaluar el operando derecho.
  2. ^ "P1161R2: Usos obsoletos del operador de coma en expresiones de subíndice". www.open-std.org . Consultado el 5 de septiembre de 2022 .
  3. ^ Mark Hoemmen; Margarita Hollman; Corentin Jabot; Isabel Muerte; Christian Trott (14 de septiembre de 2021). "Operador de subíndice multidimensional" (PDF) .
  4. ^ "SFINAE". es.cppreference.com . Consultado el 30 de agosto de 2022 .
  5. ^ Go efectivo: para "Finalmente, Go no tiene operador de coma y ++ y -- son declaraciones, no expresiones. Por lo tanto, si desea ejecutar varias variables en un for, debe usar la asignación paralela (aunque eso excluye ++ y -- ). "
  6. ^ La especificación del lenguaje de programación Go: declaraciones If
  7. ^ "Operador de coma". Documentos web de MDN . 17 de enero de 2020. Archivado desde el original el 12 de julio de 2014 . Consultado el 25 de enero de 2020 . Puede utilizar el operador de coma cuando desee incluir varias expresiones en una ubicación que requiera una sola expresión.
  8. ^ "Perlop - Operadores y precedencia de Perl - Navegador Perldoc".
  9. ^ "2.4. Notación gramatical". Corporación Oráculo . Archivado desde el original el 22 de julio de 2019 . Consultado el 25 de julio de 2019 .
  10. ^ "¿Es el operador coma (,) o el separador en Java?".

Bibliografía

enlaces externos