2010-05-19 697 views
5

Tengo el siguiente código que estoy leyendo a través de:Orden de operaciones en C. ++ vs | =, ¿qué ocurre primero?

if((i%2) == 0){ 
    *d = ((b & 0x0F) << 4); 
} 
else{ 
    *d++ |= (b & 0x0F); 
}; 

estoy buscando específicamente a la declaración else y preguntándose en qué orden se produce esto? No tengo un compilador de C normal, así que no puedo probar esto. Cuando estamos realizando *d++ |= (b & 0x0F);, ¿en qué orden ocurre esto?

+0

Ouch, estoy sorprendido o tal vez no sea aquel que primero escribió que no indicó por qué lo escribieron de esa manera. – wheaties

Respuesta

11

++ se aplica en el puntero d, no en el lvalue asignado a *d.

Si realmente desea, se puede pensar en ello como esto:

  1. El valor de b es bit a bit-Y: ed con el
  2. El patrón de bits resultante constante 0x0f es bit a bit-O: ed en el valor que d apunta a.
  3. El puntero d se incrementa para apuntar al siguiente valor.
+0

Por lo tanto, pasar a la siguiente ubicación desde el puntero ocurre DESPUÉS de que todas las operaciones se apliquen a la ubicación original. Muchas gracias. – chris

+0

No necesariamente; la semántica del operador de posfijo '++' es que el efecto secundario se aplica en algún momento antes del siguiente punto de secuencia, pero exactamente cuando eso sucede no se especifica. El compilador puede almacenar el resultado de '* d' en un temporal e inmediatamente incrementar' d' antes de hacer cualquier otra cosa. –

+0

@John: Exactamente, es por eso que escribí "si realmente quieres". – unwind

0

This link (C++ Operator Precedence) debería darle la respuesta.

2

Primero se ejecuta la parte correcta de |=, luego se realiza la asignación *d |=, luego d se incrementa. Por lo general, cuando tienes un código que genera preguntas como esa, simplemente debes reescribirlo por motivos de claridad.

5

d ++ devuelve el valor d tenido antes de que se incrementara. Esto es desreferenciado por *, y esa ubicación es en la que se realiza | | =. Por lo tanto, los datos en la ubicación antes de incrementar d tendrán en su interior (b & 0x0F).

En general, si el orden de las operaciones en una línea de código no es claro a simple vista, refactorice la línea en sus operaciones constituyentes hasta que lo esté. ¡El código generado no se vuelve más rápido o más compacto simplemente al exprimir muchas operaciones en una línea de C! No hay una buena razón para sacrificar la comprensión de esta manera. Reemplace la línea con

*d |= (b & 0x0F); 
d++; 
+0

De acuerdo. Desafortunadamente, esta es solo una porción realmente pequeña de un guión de línea de ~ 10,000 que se ve muy similar ... – chris

0

++ hecho primero. Sin embargo, el incremento posterior (es decir, d++ aquí) es equivalente a este (temp=d, d++, temp).

2

++ ocurrirá antes de |=. Los operadores de asignación se encuentran en la parte inferior del cuadro de precedencia.

0

Según http://www.cppreference.com/wiki/operator_precedence

se evaluará (b & 0x0F) a continuación, aplicar el | = a él y asignarlo a * b, finalmente, incrementar el valor que * b en señalar.

+0

'| =' tiene casi la precedencia más baja, ¿cómo se calcula que se evaluará antes del operador de incremento, que tiene casi el mayor prioridad? – meagar

0

La expresión *d++ |= (b & 0x0F) se descompone de la siguiente manera:

  1. Las expresiones *d++ y b & 0x0F están cada uno evalúa una vez (el orden en el que se evalúan no se especifica, el compilador es gratuita para evaluar b & 0x0F antes *d++ ya que la el resultado no depende del orden en que ocurre la evaluación);
  2. El resultado de (b & 0x0F) es bit-ordeñado con el resultado de *d++;
  3. El resultado de la operación bitwise-or se almacena en la ubicación apuntada originalmente por d;
  4. En algún momento de todo esto, se actualiza el valor de d.

La expresión *d++ se analiza como *(d++); es decir, está desreferenciando el resultado de la expresión d++. La expresión d++ evalúa el valor actual de d, y en un no especificado punto antes del siguiente punto de secuencia (en este caso, el final de la instrucción), se actualiza el valor de d. El efecto secundario de actualizar d no tiene que aplicarse inmediatamente; puede ocurrir antes o después de la asignación.

Cuestiones relacionadas