index.html (4591B)
1 <!DOCTYPE html> 2 <html> 3 <head> 4 <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> 5 <meta name="viewport" content="width=device-width, initial-scale=1" /> 6 <title>De los punteros en el lenguaje C</title> 7 <link rel="icon" type="image/png" href="/favicon.png" /> 8 <link rel="stylesheet" type="text/css" href="../article.css" /> 9 </head> 10 <body> 11 <header> 12 <p class="title">De los punteros en el lenguaje C</p> 13 <p class="date">24 de noviembre de 2018 • fjbalon</p> 14 </header> 15 <p>Los punteros son uno de esos elementos más confusos y complejos cuando nos iniciamos en el lenguaje C, sea que vengamos de aprender directamente a programar, o sea que vengamos de otros lenguajes de más alto nivel, como C# o Python; los punteros suelen ser una característica que conlleva sufrimiento y sacrificio. Esto son parte de mis apuntes, para dar algo de claridad a este tema, espero que el lector pueda darle utilidad.</p> 16 <p>Cada posición de memoria tiene asociada una dirección que la identifica de forma única, algo así como un identificador. Dentro de ellas se almacenan instrucciones y datos. Para que al programador le resulte más sencillo referirse a una dirección de memoria se utilizan las variables, que no son más que nombres asociados a direcciones de memoria concretas.</p> 17 <p>Las variables de tipo puntero se utilizan para almacenar en ellas la dirección de memoria de otra variable. El puntero, como variable que es, tiene asociado su dirección de memoria; y su contenido será la dirección de memoria de otra variable. Entiendo que esto es muy confuso, quizá con la siguiente imagen esté algo más claro:</p> 18 <img class="color-invertible" style="width: 300px;" src="punteros.png" /> 19 <p>Los punteros pueden apuntar a variables previamente declaradas o a variables dinámicas. <b>La potencia de los punteros reside en poder crear (reservar memoria) y destruir (liberar memoria) una variable (dinámica) en tiempo de ejecución.</b> Un puntero ocupa normalmente 4 bytes y se declara siempre de acuerdo con el tipo de dato que apunta. Tenga en cuenta que la declaración de punteros en C se realiza anteponiendo <emb>*</emb> al nombre de la variable, tal que: <emb>int * x;</emb></p> 20 <p>El lenguaje C dispone de los <b>operadores de dirección (<emb>&</emb>) e indirección (<emb>*</emb>)</b>, permitiendo respectivamenta acceder a la dirección asociada a una determinada variable y acceder al contenido de ésta (zona de memoria) a la que apunta el puntero.</p> 21 <pre><code>int i, j, *p; 22 p = &i; 23 *p = 10; 24 p = &j; 25 *p = -2; 26 p = NULL;</code></pre> 27 <p>Voy a tratar de explicar el código anterior:</p> 28 <ol> 29 <li><emb>int i, j, *p;</emb> define las variables estáticas <emb>i</emb> y <emb>j</emb>, y el puntero <emb>p</emb>.</li> 30 <li><emb>p = &i;</emb> declara o asigna a la variable <emb>p</emb> la sección de memoria de la variable <emb>i</emb>.</li> 31 <li><emb>*p = 10;</emb> asigna a la dirección de memoria a la que apunta <emb>p</emb> el valor 10.</li> 32 <li><emb>p = &j;</emb> cambia el puntero a la variable <emb>j</emb>.</li> 33 <li><emb>*p = -2;</emb> asigna dinámicamente a <emb>p</emb> el valor -2.</li> 34 <li><emb>p = NULL;</emb> hace que el puntero ya no apunte a ninguna.</li> 35 </ol> 36 <p>Podemos trabajar con punteros de tipo indefinido con <emb>void *</emb>, pudiendo asignarse cualquier tipo de puntero y valor; es un puntero genérico a alguna parte donde se almacena información de algún tipo. Es el programador el responsable de definir estos "algún" eliminando esta ambigüedad.</p> 37 <pre><code>int x = 1; 38 float r = 1.0; 39 40 void* ptr = &x; 41 *(int *)ptr = 2; 42 43 ptr = &r; 44 *(float *) ptr = 1.1;</code></pre> 45 <p>Las <b>operaciones aritméticas entre punteros</b> en el lenguaje C se limitan a suma, resta, comparación y asignación. Estas operaciones a un tipo de dato x tienen automáticamente en cuenta el tamaño que ocupa ese tipo de dato en memoria. Es decir, el número de bytes necesario para almacenar un objetivo de ese tipo de dato: la suma incrementa la dirección a la que apunta el puntero teniendo en cuenta el tipo de dato al que apunte el puntero. O sea, si un puntero apunta a un tipo de dato entero y le suma 1, se desplaza el tamaño de un entero. En el caso de la resta, se decrementa la dirección.</p> 46 <p>Estas dos operaciones son útiles cuando trabajamos con vectores o matrices (lineal) y la suma o resta permitirían moverse entre los elementos de éste.</p> 47 <pre><code>int a, b, c; 48 int *p1, *p2; 49 void *p; 50 51 p1 = &a; 52 *p1 = 1; 53 54 p2 = &b; 55 *p2 = 2; 56 57 p1 = p2; 58 *p1 = 0; 59 60 p2 = &c; 61 *p2 = 3; 62 63 p = &p1; 64 *p = p2; 65 *p1 = 1;</code></pre> 66 </body> 67 </html>