Pregunta

Lo que hace el , operador hace en C?

¿Fue útil?

Solución

La expresion:

(expression1,  expression2)

Primero se evalúa la expresión1, luego se evalúa la expresión2 y se devuelve el valor de la expresión2 para toda la expresión.

Otros consejos

He visto usado más en while bucles:

string s;
while(read_string(s), s.len() > 5)
{
   //do something
}

Realizará la operación y luego realizará una prueba basada en un efecto secundario.La otra forma sería hacerlo así:

string s;
read_string(s);
while(s.len() > 5)
{
   //do something
   read_string(s);
}

El operador de coma evaluará el operando izquierdo, descartará el resultado y luego evaluará el operando derecho y ese será el resultado.El idiomático El uso como se indica en el enlace es al inicializar las variables utilizadas en un for bucle, y da el siguiente ejemplo:

void rev(char *s, size_t len)
{
  char *first;
  for ( first = s, s += len - 1; s >= first; --s)
      /*^^^^^^^^^^^^^^^^^^^^^^^*/ 
      putchar(*s);
}

Por lo demás no hay muchos excelente Usos de la operador de coma, aunque es fácil de abusar para generar código que sea difícil de leer y mantener.

Desde el borrador del estándar C99 la gramática es la siguiente:

expression:
  assignment-expression
  expression , assignment-expression

y Párrafo 2 dice:

El el operando izquierdo de un operador de coma se evalúa como una expresión nula; hay un punto de secuencia después de su evaluación.Entonces el se evalúa el operando derecho;el resultado tiene su tipo y valor. 97) Si se intenta modificar el resultado de un operador de coma o acceder a él después del siguiente punto de secuencia, el comportamiento no está definido.

Nota al pie 97 dice:

Un operador de coma hace no produce un valor l.

lo que significa que no se puede asignar al resultado de la operador de coma.

Es importante tener en cuenta que el operador de coma tiene la precedencia más baja y por lo tanto hay casos en los que usar () puede marcar una gran diferencia, por ejemplo:

#include <stdio.h>

int main()
{
    int x, y ;

    x = 1, 2 ;
    y = (3,4) ;

    printf( "%d %d\n", x, y ) ;
}

tendrá el siguiente resultado:

1 4

El operador de coma combina las dos expresiones a cada lado en una, evaluándolas en orden de izquierda a derecha.El valor del lado derecho se devuelve como el valor de toda la expresión. (expr1, expr2) es como { expr1; expr2; } pero puedes usar el resultado de expr2 en una llamada de función o asignación.

A menudo se ve en for bucles para inicializar o mantener múltiples variables como esta:

for (low = 0, high = MAXSIZE; low < high; low = newlow, high = newhigh)
{
    /* do something with low and high and put new values
       in newlow and newhigh */
}

Aparte de esto, sólo lo he usado "con ira" en otro caso, al concluir dos operaciones que siempre deberían ir juntas en una macro.Teníamos un código que copiaba varios valores binarios en un búfer de bytes para enviarlos a una red, y manteníamos un puntero donde habíamos llegado a:

unsigned char outbuff[BUFFSIZE];
unsigned char *ptr = outbuff;

*ptr++ = first_byte_value;
*ptr++ = second_byte_value;

send_buff(outbuff, (int)(ptr - outbuff));

donde estaban los valores shorts o intEntonces hicimos esto:

*((short *)ptr)++ = short_value;
*((int *)ptr)++ = int_value;

Más tarde leemos que esto no era realmente válido en C, porque (short *)ptr ya no es un valor l y no se puede incrementar, aunque a nuestro compilador en ese momento no le importó.Para solucionar este problema, dividimos la expresión en dos:

*(short *)ptr = short_value;
ptr += sizeof(short);

Sin embargo, este enfoque dependía de que todos los desarrolladores recordaran incluir ambas declaraciones en todo momento.Queríamos una función donde se pudiera pasar el puntero de salida, el valor y el tipo de valor.Al ser C, no C++ con plantillas, no podíamos hacer que una función tomara un tipo arbitrario, así que nos decidimos por una macro:

#define ASSIGN_INCR(p, val, type)  ((*((type) *)(p) = (val)), (p) += sizeof(type))

Al usar el operador de coma pudimos usar esto en expresiones o declaraciones como quisiéramos:

if (need_to_output_short)
    ASSIGN_INCR(ptr, short_value, short);

latest_pos = ASSIGN_INCR(ptr, int_value, int);

send_buff(outbuff, (int)(ASSIGN_INCR(ptr, last_value, int) - outbuff));

¡No estoy sugiriendo que ninguno de estos ejemplos tenga buen estilo!De hecho, creo recordar la frase de Steve McConnell. Código completo desaconsejando incluso el uso de operadores de coma en un for bucle:Para facilitar la lectura y el mantenimiento, el bucle debe estar controlado por una sola variable y las expresiones en el for La línea en sí solo debe contener código de control de bucle, no otros bits adicionales de inicialización o mantenimiento de bucle.

Provoca la evaluación de múltiples declaraciones, pero usa solo la última como valor resultante (rvalue, creo).

Entonces...

int f() { return 7; }
int g() { return 8; }

int x = (printf("assigning x"), f(), g() );

debería dar como resultado que x se establezca en 8.

El operador de coma no hace nada significativo, es una característica 100% superflua.Su uso principal es "personas que intentan ser inteligentes" y, por lo tanto, lo utilizan para ofuscar (sin querer) código legible.El área principal de uso es ofuscar bucles for, por ejemplo:

for(int i=0, count=0; i<x; i++, count++)

Dónde int i=0, count=0 en realidad no es el operador de coma, sino una lista de declaraciones (aquí ya estamos confundidos). i++, count++ es el operador de coma, que evalúa primero el operando izquierdo y luego el operando derecho.El resultado del operador coma es el resultado del operando derecho.El resultado del operando izquierdo se descarta.

Pero el código anterior podría escribirse de una forma mucho más legible sin el operador de coma:

int count = 0;
for(int i=0; i<x; i++) // readable for loop, no nonsense anywhere
{
  ...
  count++;
}

El único uso real del operador de coma que he visto son las discusiones artificiales sobre puntos de secuencia, ya que el operador de coma viene con un punto de secuencia entre la evaluación de los operandos izquierdo y derecho.

Entonces, si tienes algún código de comportamiento indefinido como este:

printf("%d %d", i++, i++);

De hecho, puedes convertirlo en un comportamiento meramente no especificado (orden de evaluación de los parámetros de la función) escribiendo

printf("%d %d", (0,i++), (0,i++));

Ahora hay un punto de secuencia entre cada evaluación de i++, por lo que al menos el programa ya no correrá el riesgo de fallar y quemarse, aunque el orden de evaluación de los parámetros de la función permanezca sin especificar.

Por supuesto, nadie escribiría ese código en aplicaciones reales; sólo es útil para discusiones entre abogados sobre puntos de secuencia en lenguaje C.

El operador de coma está prohibido por MISRA-C:2004 y MISRA-C:2012 con el argumento de que crea código menos legible.

Como han indicado respuestas anteriores, evalúa todas las declaraciones pero usa la última como valor de la expresión.Personalmente sólo lo he encontrado útil en expresiones de bucle:

for (tmp=0, i = MAX; i > 0; i--)

El único lugar en el que he visto que es útil es cuando escribes un bucle original en el que quieres hacer varias cosas en una de las expresiones (probablemente la expresión init o la expresión de bucle).Algo como:

bool arraysAreMirrored(int a1[], int a2[], size_t size)
{
  size_t i1, i2;
  for(i1 = 0, i2 = size - 1; i1 < size; i1++, i2--)
  {
    if(a1[i1] != a2[i2])
    {
      return false;
    }
  }

  return true;
}

Disculpe si hay algún error de sintaxis o si mezclé algo que no sea C estricto.No estoy diciendo que el operador , sea bueno, pero para eso podrías usarlo.En el caso anterior probablemente usaría un while bucle en su lugar para que las múltiples expresiones en init y loop sean más obvias.(Y inicializaría i1 e i2 en línea en lugar de declarar y luego inicializar....bla, bla, bla.)

Estoy reviviendo esto simplemente para responder las preguntas de @Rajesh y @JeffMercado que creo que son muy importantes ya que este es uno de los principales resultados en los motores de búsqueda.

Tome el siguiente fragmento de código, por ejemplo

int i = (5,4,3,2,1);
int j;
j = 5,4,3,2,1;
printf("%d %d\n", i , j);

Se imprimirá

1 5

El i El caso se maneja como se explica en la mayoría de las respuestas.Todas las expresiones se evalúan en orden de izquierda a derecha, pero solo la última se asigna a i.El resultado de la ( expresión )is1`.

El j caso sigue diferentes reglas de precedencia ya que , tiene la precedencia de operador más baja.Debido a esas reglas, el compilador ve asignación-expresión, constante, constante....Las expresiones se evalúan nuevamente en orden de izquierda a derecha y sus efectos secundarios permanecen visibles, por lo tanto, j es 5 como resultado de j = 5.

Curiosamente, int j = 5,4,3,2,1; no está permitido por la especificación del idioma.Un inicializador espera un expresión-asignación entonces un directo , El operador no está permitido.

Espero que esto ayude.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top