todas - ¿Qué significa si((x=0)) significa en C?
precedencia de operadores en c (3)
No hay diferencia, en cuanto al código.
Todo lo que sucede es que decir x=0
lugar de x==0
es un error tan común que la mayoría de los compiladores emitirán una advertencia (o error, en su caso) cuando lo vean. El conjunto adicional de paréntesis es un truco común para cerrar el compilador, el equivalente a decir ''sí, realmente quise hacer esto''.
Entonces, aparentemente, en gcc / C, un compilador compila cuando
if ((x=0)){ some code }
se usa, mientras que cuando
if (x=0){ some code }
se usa, el compilador se niega a compilar.
¿Cuáles son las diferencias entre dos?
Como nota, sé cuál es la diferencia entre x==0
y x=0
. Solo estoy explorando cómo se comporta C cuando se encuentra con algunos códigos raros.
Ambos son sintácticamente correctos C y el compilador tiene que lidiar con eso. Pero el compilador puede, dependiendo de la configuración, emitir una advertencia o incluso un error (por ejemplo, "Error en gcc") porque uno de ellos es tan sospechoso que nunca esperaría que fuera intencional. Cuando usas algo como if (x = 0) { ... }
(asignar cero a x
y ejecutar el bloque si cero no es cero), casi siempre significas if (x == 0) { ... }
(ejecuta el bloque si x
es cero).
Ahora veamos por qué if ((x = 0)) { ... }
no se considera lo suficientemente sospechoso para garantizar el mismo tipo de advertencia (este código en particular aún es sospechoso porque la condición siempre se evalúa a cero y el cuerpo nunca se ejecuta ) ...
Hay un modismo usado por algunos desarrolladores de C (yo soy uno de ellos) en el que colocas una asignación entre paréntesis y haces uso de la función de que incluso la asignación tiene un valor en sí mismo y es el valor asignado.
Ejemplo:
#include <stdio.h>
int main(int argc, char **argv)
{
int c;
while ((c = getchar()) != ''/n'')
printf("Character: ''%c'' (0x%02x)/n", c, c);
return 0;
}
Pruebe el ejemplo:
$ ./test
Hello!
Character: ''H'' (0x48)
Character: ''e'' (0x65)
Character: ''l'' (0x6c)
Character: ''l'' (0x6c)
Character: ''o'' (0x6f)
Character: ''!'' (0x21)
La parte más importante fue la condición (c = getchar()) != ''/n''
donde primero asignas el resultado de getchar()
a c
y luego lo compruebas para un valor específico. En este caso, estamos leyendo caracteres uno por uno desde la entrada estándar hasta el y de una línea (técnicamente hasta que leemos un carácter /n
). La principal ventaja de hacerlo de esta manera es que te permite meter el getchar()
en la prueba. De lo contrario, tendría que usar la notación de coma, un bucle infinito con un descanso, o ponerlo antes del bucle y al final del bucle.
A veces se compara con valores distintos de cero, como /n
, -1
y similar, pero a veces se compara con cero o, cuando se trabaja con punteros, con NULL
. Vamos a encontrar un ejemplo para NULL
, que es bastante común con la asignación de memoria.
char *p;
if ((p = malloc(50)) == NULL) {
...handle error...
}
Por supuesto, podrías escribirlo como:
char *p;
p = malloc(50);
if (p == NULL) {
...handle error...
}
Pero dependiendo de tu gusto también puedes usar:
char *p;
if (!(p = malloc(50))) {
...handle error...
}
O incluso gire al revés (lo que por cierto va en contra de mi preferencia de siempre manejar primero el caso de error):
char *p;
if ((p = malloc(50))) {
...do stuff...
} else {
...handle error...
}
En el último caso, la condición es (p = malloc(50))
que es exactamente equivalente a p = malloc(50)
pero esta última es altamente sospechosa debido al error común ya mencionado de realizar la asignación en lugar de la comparación en C y derivado idiomas. Tenga en cuenta que esto no se trata solo de compiladores sospechosos sino también de personas que leen el código y observan el error potencial.
Los paréntesis redundantes son simplemente un medio para decirle a los lectores y al compilador que esta asignación es definitivamente intencional y que no es una ocurrencia de ese error común.
El código no debe "negarse" a compilar a menos que tenga -Werror
. Si tiene advertencias habilitadas, podría decirle:
advertencia: sugiere paréntesis alrededor de la asignación utilizada como valor de verdad [-Wparentheses]
while (*dest++ = *src++)
Específicamente, los documentos de GCC dicen esto sobre el propósito de la advertencia:
Advierta si los paréntesis se omiten en ciertos contextos, como cuando hay una asignación en un contexto donde se espera un valor de verdad, o cuando los operadores están anidados cuya prioridad a menudo las personas se confunden.