CAPÍTULO 4: Más sobre Cadenas de Texto

Bien, ¡hemos avanzado mucho en poco tiempo! Vamos a retroceder un poco para ver lo que hicimos en el Capítulo 3 cuando copiábamos cadenas de texto, pero ahora lo haremos desde una perspectiva diferente. Consideremos la siguiente función:
    char *mi_copiacadena(char destino[], char origen[])
    {
        int i = 0;
        while (origen[i] != '\0')
        {
            destino[i] = origen[i];
            i++;
        }
        destino[i] = '\0';
        return destino;
    }
Recordemos que las cadenas de texto son arrays de caracteres. Para esta copia hemos utilizado la notación de array en lugar de la notación de punteros. El resultado es el mismo, es decir, con esta notación la cadena se copia con la misma precisión que en el ejemplo anterior con punteros. Esto plantea algunas cosas interesantes que vamos a ver.

Como los parámetros se pasan por valor, tanto si pasamos un puntero a un caracter como si pasamos el nombre del array, como hemos visto antes, lo que realmente se pasa es la dirección del primer elemento de cada array. Por lo tanto, el valor numérico del parámetro que se pasa a la función es el mismo, tanto si se utiliza un puntero a un caracter como si utilizamos un nombre de array. Esto implica de alguna manera que origen[i] es lo mismo que *(p+i).

De hecho esto es cierto, es decir, donde escribimos a[i], puede ser reemplazado con *(a + i) sin ningún problema, pues el compilador creará el mismo código en ambos casos. Así vemos que la aritmética de punteros es lo mismo que la indexación de un array. Ambas sintáxis producen el mismo resultado.

Esto NO quiere decir que los punteros y los arrays sean la misma cosa, porque no lo son. Sólo decimos que para identificar un elemento de un array podemos elegir una de entre dos sintáxis: una utiliza la indexación de un array y la otra utiliza aritmética de punteros, ambas con el mismo resultado.

Ahora miremos una parte concreta de esta última expresión: (a + i), que es una adición simple utilizando el operador + . Las reglas de C indican que esta expresión es conmutativa, esto es: (a + i) es idéntico a (i + a), por eso podemos escribir *(i + a) como *(a + i) y obtendremos el mismo resultado.

Pero *(i + a) podría haber venido de i[a] curiosamente:

    char a[20];
    int i;
si escribirmos
    a[3] = 'x';
es lo mismo que si escribimos
    3[a] = 'x';
¡Pruébalo! Crea un array con elementos de tipo char, int o long, etc, después al elemento 3 o 4 asígnale un valor de forma convencional y después muestra el resultado. Después invierte la notación del array como acabamos de ver. Un buen compilador no apreciará la diferencia y los resultados serán idénticos. Esto es una curiosidad... ¡nada más!

Ahora, volviendo a la función de antes, cuando escribimos:

    destino[i] = origen[i];
como la indexación de arrays y la aritmética de punteros dan los mismos resultados, podemos escribirlo como:
    *(destino + i) = *(origen + i);
Aquí vemos dos adiciones por cada valor de i, y normalmente las adiciones tardan más que las incrementaciones (como las realizadas con el operador ++ como en i++). En compiladores modernos y optimizados es posible que no sea así, pero uno nunca sabe. Por lo tanto, la versión con punteros puede ser un poco más rápida que la versión con arrays.

Otra forma de acelerar la versión con punteros sería cambiar:

    while (*origen != '\0')
a simplemente:
    while (*origen)
puesto que en ambos casos el valor dentro del paréntesis será cero (FALSE).

En este punto es posible que quieras experimentar un poco escribiendo tus propios programas utilizando punteros para manipular cadenas de texto. También es posible que quieras escribir tus propias versiones de funciones estándar como:

    strlen();
    strcat();
    strchr();
y de cualquier otra que tengas en tu sistema.

Volveremos con las cadenas de texto y su manipulación mediante punteros en un capítulo posterior. En el siguiente capítulo vamos a ver un poco de estructuras.

Continuar con el Tutorial de Punteros

Tabla de Contenidos