2010-02-09 9 views
7

Estoy confundido acerca de este código: (http://www.joelonsoftware.com/articles/CollegeAdvice.html)Copia de una cadena en C

while (*s++ = *t++); 

¿Cuál es el orden de ejecución? ¿Se hace * s = * t primero, y luego cada uno se incrementa? O de otra manera?

Gracias.

EDIT: ¿Y si era:

while(*(s++) = *(t++)); 

y

while(++*s = ++*t); 
+1

Me pregunto si Joel aún estaría de acuerdo con ese artículo de hace 5 años ... ¿te importaría comentar a Joel? – Hogan

+0

Sugiero que todos comiencen a colocar el punto y coma en la línea siguiente, en lugar de justo después de la condición de ciclo, en ciclos while con una declaración nula para el cuerpo. Realmente creo que es mucho más claro y fácil de leer. –

Respuesta

14
while (*s++ = *t++); 

Desde el precedence table se puede ver claramente ++ es tener mayor precedencia que *. Pero ++ se usa aquí como operador de incremento posterior, por lo que el incremento ocurre después de la expresión de asignación. Entonces *s = *t ocurre primero, luego s y t se incrementan.

EDIT:

while(*(s++) = *(t++)); 

Es igual que el anterior. Lo estás haciendo más explícito con el uso de paréntesis. Pero recuerda ++ sigue siendo un incremento de publicación.

while(++*s = ++*t); 

Solo hay un operador al lado de s. Por lo tanto, * se aplica primero y en ese resultado se aplica ++ que da como resultado el error lvalue required.

while(*++s = *++t); 

De nuevo solo operador al lado de s, t. Entonces el incremento ocurre primero seguido de copia. Así que estamos omitiendo la copia del primer carácter char de t para s.

+0

¿No es "precedencia" y no "precedencia"? Puede ser algo británico/americano, así que no quiero editar ... –

2

el incremento es de un incremento posterior. Publicar no solo porque viene después de que la variable se incrementa, sino también porque viene después de que se evalúa la expresión. Por lo que el orden de ejecución es

*s = *t 

entonces s ++ y t ++

1

EDITAR ::

@chrisgoyal

orden de ejecución es un término ambiguo. Hay dos cosas diferentes aquí. El orden sintáctico y la semántica de la expresión.

Sintácticamente, el operador ++ se aplica primero. Si se aplica por primera vez el * s, entonces lo siguiente es equivalente a lo que dijo @Hogan:

(*s)++ = (*t)++ 

Cuál es muy diferente de la muestra de Joel.

La semántica del operador ++ es que se ejecuta después de la expresión.

Espero que aclare lo que carne.


En realidad, s++ y t++ se aplican en primer lugar. No olvide que el operador posterior a la corrección es ejecutado después de la expresión está hecha. Básicamente, el operador ++ se aplica para ambos, , luego*s = *t se ejecuta.

+0

err ... después de los medios después de la derecha. Usted describió el incremento que sucedía antes. – Hogan

+0

@Hogan el operador de reparación posterior tiene ** prioridad más alta **, por lo que se aplica primero. La * semántica * del operador posterior a la corrección se aplica * después * de que la expresión esté lista. – AraK

+0

Tu respuesta dice dos cosas diferentes ... – chrisgoyal

4

Tienes razón. * s = * t se hace primero, y luego se incrementan.

0

En Incremento de publicación, la variable de operación se usa primero y luego se modifica.

0

Así que hay dos formas de incremento

++s // increment before using value 
s++ // increment after using value 

Y el resultado de estos pueden ser dereferenced:

*++s // or... 
*s++ 

Esto funcionó muy bien en una de las primeras máquinas para C para funcionar encendido, el PDP-11, que tenía un modo de direccionamiento indirecto de registro que incrementa el registro después. Las siguientes operaciones estaban disponibles en el hardware:

*--s // or 
*s++ 

que podría hacer cualquiera

*x++ = *y++; // or 
*--x = *--y; // or some combination 

Y si lo hizo, toda la línea ocurrieron en una sola instrucción. Dado que // los comentarios fueron introducidos por C99, sin embargo, no se pudo salir con la sintaxis de mi comentario.

+0

Puede salirse con '//' comentarios usando el 99% de los compiladores de C. No es una buena idea, pero dudo que mate a nadie. –

+0

Como de costumbre, tiene razón, y estoy totalmente de acuerdo, pero estaba especulando que no habrían trabajado en el compilador PDP-11 C ... – DigitalRoss

0

El código: (while *s++ = *t++); es más o menos equivalente a:

while (*s = *t) { 
    ++s; 
    ++t; 
} 

La segunda es exactamente la misma - los parens adicionales no cambian nada (en este caso). Para que los padres hagan algo, tendrían que ser como: while ((*s)++ = (*t)++);. Esto haría más o menos lo mismo que su tercer ejemplo (cubierto en el párrafo siguiente).

El último ejemplo: while(++*s = ++*t); es completamente diferente. Como la desreferencia (*) está más cerca del operando, esto desreferencia el operando e incrementa el resultado de la desreferencia, lo que significa que incrementa lo que el puntero apunta a AT, en lugar de incrementar el puntero mismo. Como resultado, esto copiaría el primer carácter, luego incrementaría ese carácter, luego verificaría si ese carácter no era cero y continuaría igual hasta que fuera cero. El resultado sería tanto el origen como el destino convirtiéndose en cadenas vacías (ya que el primer carácter de ambos sería ahora cero, que se usa para terminar cadenas).