2012-06-18 20 views
7

Tenía la impresión de que postincrement (O preincrement) solo se puede hacer en el lado derecho de igual (=). Pero puedo compilar debajo del código. ¿Puede ayudarme a comprender este código específico, especialmente debajo de la línea? fuente: http://www.ibm.com/developerworks/library/pa-dalign/postincrement en el lado izquierdo

*data8++ = -*data8; 


void Munge8(void *data, uint32_t size) { 
    uint8_t *data8 = (uint8_t*) data; 
    uint8_t *data8End = data8 + size; 

    while(data8 != data8End) { 
     *data8++ = -*data8; 
    } 
} 
+0

Asignar '- * * data8' a' 'data8' luego incrementar data8' - negando efectivamente el' 'size' bytes en data' – Erik

Respuesta

3

Su impresión es errónea, supongo. Definitivamente, usted puede hacer cosas como:

*a++ = *b++; 

De hecho, eso es a menudo cómo se implementa strcpy. Incluso puede tener el post o pre-incrementos sin un = en absoluto:

a++; 
+0

Espere, así que estaba de acuerdo con tu publicación original. ¿Cómo es este comportamiento no definido? –

+0

strcpy no está implementado así. En primer lugar, busca el final de la cadena en patrones de bits de trozos de datos más grandes, luego copia los datos en trozos más grandes (generalmente 64 bits). –

+0

@sharth: ¿Cómo es indefinido? No soy un drogadicto estándar, pero RHS debe evaluarse primero y luego LHS. Por lo tanto, no debería haber problemas. –

1

No hay razón por la post-incremento no se puede hacer en el lado izquierdo del operador de asignación. Un operador de incremento posterior simplemente devuelve una copia temporal del objeto en su estado anterior, y ese objeto temporal (en este caso un puntero) puede realizar operaciones en él.

Ahora, en el caso de:

*data8++ = -*data8; 

debido a pedido del operador, el puntero data8 primero será post incrementado, devolviendo una copia del valor del puntero anterior. El valor del puntero anterior será desreferenciado y se le asignará el resultado de la expresión en el lado derecho del operador de asignación.

Editar: Como otros han señalado, que se está modificando el contenido de data8 mediante la lectura de más de una vez al escribir en esa ubicación de memoria sin un punto de la secuencia, por lo que este es un comportamiento indefinido.

+0

¿Cómo es esto indefinido? Es como decir 'x = -x' no está definido. –

+0

Está modificando el contenido de 'data8' (es decir, el valor del puntero) y luego lo lee en dos ubicaciones diferentes sin un punto de secuencia. Como han señalado otros, obtendrá dos resultados diferentes si primero se evalúa el LHS o el RHS ... por lo tanto, "comportamiento indefinido" ya que el estándar C no define qué lado se debe evaluar primero ... por ejemplo, el ¡las evaluaciones de LHS y RHS podrían ser intercaladas!En su ejemplo, hay un orden de evaluación claro ya que el LHS no está leyendo el valor de 'x', simplemente está escribiendo en él. Entonces solo hay una sola lectura/escritura. – Jason

+0

Sí. Reclamaré la falta de sueño como una excusa. –

2

++ se aplica al puntero, no al valor apuntado por data8.

*data8++ = -*data8;

es equivalente a:

*data8 = -*data8; 
data8++; 

EDIT:
Después de leer el C99 standard 6.5 y Annex C, está claro = no es un punto de secuencia. La norma menciona solo &&, ||, , y ?.

Dado que, data8 se modifica a ambos lados de = que ningún punto de la secuencia y Norma no se establece si RHS debe ser evaluado primero o LHS se debe evaluar en primer lugar, estoy convencido de que esto es comportamiento indefinido.

Any good reason why assignment operator isn't a sequence point?

Este post anterior discute = no siendo un punto de secuencia y es bastante relacionadas aquí.

+0

'data8' no se modifica en ambos lados del operador de asignación, sino que se modifica en el LHS, pero se lee dos veces sin un punto de secuencia que determine cómo se secuencian las lecturas frente a la escritura. – Jason

+0

@Jason tienes razón. '=' no ser un punto de secuencia es la clave aquí. –

7

Por lo tanto, estoy bastante seguro de que este comportamiento no está definido.No hay punto secuencia distinta de la coma final en:

*data8++ = -*data8; 

Si Data8 es igual a 0x20, es esta igual a:

*(0x20) = -*(0x20); 

o

*(0x20) = -*(0x24); 

porque no hay forma de tomar esta decisión, (porque editó una variable mientras la leía dos veces, sin punto de secuencia de intercalación), esto es comportamiento indefinido.


Sin embargo, podemos hablar de lo que hace el siguiente fragmento de código. Que es probable lo que pretende el código anterior.

while(data8 != data8End) { 
    *data8 = -*data8; 
    data8++; 
} 

Lo que estás haciendo aquí es, con suerte, más directo. Estás tomando tu matriz de entrada, y mirándola para que sea una serie de números de 8 bits. Luego, en el lugar, niegas cada uno.

+0

Creo que estás confundiendo "variables" aquí. El valor y el valor del puntero almacenados en el puntero de dirección son dos cosas diferentes. Nadie en este caso ha editado una variable mientras la leía dos veces. El valor en el puntero de la dirección por "data8" se lee una vez en el RHS. Está escrito una vez. El puntero se cambia una vez en el LHS. –

+0

O tal vez yo. Hehe –

+2

@Vlad, an '=' no es un punto de secuencia. –

0

creo que

* Data8 ++ = - * Data8;

es equivalente a

* Data8 = - * (Data8 + 1);

Data8 = 1 Data8

Cuestiones relacionadas