5.5 punteros a carácter y funciones
A constante de cadena, escrito como
"I am a string"
es un array de caracteres. En la representación interna, la matriz finaliza con el carácter nulo '\0'
para que los programas puedan encontrar el final. La longitud de almacenamiento es, por lo tanto, uno más que el número de caracteres entre las comillas dobles.
Tal vez el caso más común de las constantes de cadena es como argumentos a funciones, como en
printf("hello, world\n");
Cuando una cadena de caracteres como éste aparece en un programa, el acceso a ella es a través de un puntero de carácter; printf
recibe un puntero al comienzo de la matriz de caracteres. Es decir, se accede a una constante de cadena mediante un puntero a su primer elemento.
Las constantes de cadena no necesitan ser argumentos de funciones. Si pmessage
está declarada como
char *pmessage;
entonces la declaración
pmessage = "now is the time";
asigna a pmessage
un puntero a la matriz de caracteres. Esto es no una copia de cadena; solo punteros están involucrados. C no proporciona operadores para procesar una cadena completa de caracteres como una unidad.
Hay una diferente importante entre estas definiciones:
char amessage[] = "now is the time"; /* an array */
char *pmessage = "now is the time"; /* a pointer */
amessage
es una matriz, lo suficientemente grande para contener la secuencia de caracteres y '\0'
que lo inicializa. Los caracteres individuales dentro de la matriz pueden cambiarse por amessage
siempre se referirán al mismo almacenamiento. Por otro lado, pmessage
es un puntero, inicializado para apuntar a una constante de cadena; el puntero puede modificarse posteriormente para apuntar a otro lugar, pero el resultado no está definido si intenta modificar los contenidos de la cadena.
+---+ +--------------------+
pmessage: | o-------->| now is the time \0 |
+---+ +--------------------+
+--------------------+
amessage: | now is the time \0 |
+--------------------+
Ilustraremos más aspectos de punteros y matrices estudiando las versiones de dos funciones útiles adaptadas de la biblioteca estándar. La primera función es strcpy(s,t)
, que copia la cadena t
en la cadena s
. Sería bueno simplemente decir s = t
pero esto copia el puntero, no los caracteres. Para copiar los caracteres, necesitamos un ciclo. La versión de matriz es primero:
/* strcpy: copy t to s; array subscript version */
void strcpy(char *s, char *t)
{
int i;
i = 0;
while((s[i] = t[i]) != '\0')
i ++;
}
Por el contrario, aquí es una versión de strcpy
con punteros:
/* strcpy: copy t to s; pointer version 1 */
void strcpy(char *s, char *t)
{
while((*s = *t) != '\0')
{
s ++;
t ++;
}
}
porque los argumentos se pasan por valor, strcpy
puede usar los parámetros s
y t
en modo alguno eso agrada. Aquí están los punteros convenientemente inicializados, que se marchan a lo largo de las matrices un carácter a la vez, hasta que '\0'
que termina t
se haya copiado al s
.
En la práctica, strcpy
no estaría escrito como lo mostramos arriba. Experimentados programadores de C preferirían
/* strcpy: copy t to s; pointer version 2 */
void strcpy(char *s, char *t)
{
while((*s++ = *t++) != '\0')
;
}
Esto mueve el incremento de s
y t
en la parte de la prueba del bucle. El valor de *t++
es el carácter que se incrementó en t
antes de t
; el postfijo ++
no cambia t
hasta después de que se haya obtenido este caracter. De la misma manera, el carácter se almacena en la antigua posición s
antes de que se incremente s
. Este caracter también es el valor que se compara con '\0'
para controlar el ciclo. El efecto neto es que los caracteres se copian de t
a s
, hasta e incluyendo la terminación '\0'
.
Como abreviatura final, observe que una comparación contra '\0'
es redundante, ya que la pregunta es simplemente si la expresión es cero. Por lo tanto la función es probable que se escribe como
/* strcpy: cope t to s; pointer version 3 */
void strcpy(char *s, char *t)
{
while(*s++ = *t++);
}
Aunque esto puede parecer críptico primera vista, la conveniencia de notación es considerable, y el lenguaje debe ser dominado, porque verá si con frecuencia en programas C.
El strcpy
en la biblioteca estándar (<string.h>
) devuelve la cadena de destino como su valor de función.
Éste es el final de las partes pertinentes de esta sección.
PD: Si le gustó leer esto, considere comprar una copia de K & R - no es caro.
Consulte mi respuesta a continuación. Esta respuesta es incorrecta –