commit d49b5e304fcc93f8487141452de9533c61df25ef
parent 6ee976588900811b9d172bf3dca8d491d48e7420
Author: fjbalon <fbalon@templier.es>
Date: Fri, 3 Jul 2026 00:14:59 +0200
Añadidos artículos antiguos sobre make y punteros
Diffstat:
4 files changed, 173 insertions(+), 0 deletions(-)
diff --git a/index.html b/index.html
@@ -394,6 +394,11 @@
<p class="info">1 de enero de 2019 · fjbalon</p><p>Qemu, que yo pronuncio como Khemu /xɛ̃mu/ -sí, el hijo de Bayek de Siwa-, es un potente software de virtualización y emulación....</p>
</a>
+<a href="./programacion-c-punteros/" class="article">
+ <p class="title">De los punteros en el lenguaje C</p>
+ <p class="info">24 de noviembre de 2018 · fjbalon</p><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 ...</p>
+</a>
+
<a href="./denis-ritchie-unix/" class="article">
<p class="title">Unix es simple. Sólo se necesita un genio para entender su simplicidad, de Denis Ritchie</p>
<p class="info">2 de julio de 2018 · fjbalon</p><p>Unix es un sistema, aunque pensemos en éste de una forma abstracta y conceptual de cara a la filosofía, que se basa en módulos pequeños y simples. Sin embargo, decir que por ello Unix es simple se...</p>
@@ -429,6 +434,11 @@
<p class="info">24 de mayo de 2016 · fjbalon</p><p>Buenos días. La siguiente entrada documenta cómo realizar una prueba de concepto que consiste en realizar una inyección SQL básico en un programa Java con JDBC (Java DataBase Connectivity). Ademá...</p>
</a>
+<a href="./make/" class="article">
+ <p class="title">De las herramientas make y cmake</p>
+ <p class="info">1 de mayo de 2016 · fjbalon</p><p>Make es una herramienta de gestión de dependencias usada en entornos de la familia UNIX. Es una buena práctica para compilar de forma automatizada códigos compuestos y complejos, por ejemplo en có...</p>
+</a>
+
<a href="./permisos-unix/" class="article">
<p class="title">De la heredad de permisos y propietarios de Unix</p>
<p class="info">2 de abril de 2016 · fjbalon</p><p>La comprensión del fichero o archivo, file para los anglosajones, es fundamental para comprender la estructura y funcionamiento lógico de Unix. Un fichero es una colección de bytes agrupados bajo u...</p>
diff --git a/make/index.html b/make/index.html
@@ -0,0 +1,94 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
+<meta name="viewport" content="width=device-width, initial-scale=1" />
+<title>De las herramientas make y cmake</title>
+<link rel="icon" type="image/png" href="/favicon.png" />
+<link rel="stylesheet" type="text/css" href="../article.css" />
+</head>
+<body>
+<header>
+<p class="title">De las herramientas make y cmake</p>
+<p class="date">1 de mayo de 2016 • fjbalon</p>
+</header>
+<p>Make es una herramienta de gestión de dependencias usada en entornos de la familia UNIX. Es una buena práctica para compilar de forma automatizada códigos compuestos y complejos, por ejemplo en códigos compuestos de códigos C en distintos ficheros con distintos ficheros de cabecera <emb>.h</emb>.</p>
+<p>Para preparar el funcionamiento de make es necesario crear un fichero, en el cual se especifica y se configura todo lo necesario para el proceso. Este fichero es denominado makefile. Podemos decir que son las instrucciones que make debe realizar.</p>
+<p>Como añadido, make entiende los formatos y extensiones, dando una respuesta apropiada a cada tipo de archivo.</p>
+<p>El formato genérico para un makefile es el siguiente:</p>
+<pre><code>VARIABLES
+...
+
+OBJETIVO: DEPENDENCIAS
+ COMANDO
+ ...</code></pre>
+<p>Un makefile simple para realizar con make la compilación de un programa C sería similar al siguiente:</p>
+<pre><code>hola: hola.c
+ gcc -o hola hola.c -I.\end{lstlisting}
+
+Podemos mejorarlo aún más para que sólo compile los ficheros que han cambiado desde el
+último make, para ello sería similar al siguiente:
+
+\begin{lstlisting}[language=make]
+# Vease el cambio de los ficheros .c a .o.
+# Internamente make sabe que los .o son .c
+# y asi los busca y compila; ignorando los
+# encabezados.
+CC=gcc
+CFLAGS=-I.
+
+hola: hola.o
+ $(CC) -o hola hola.o</code></pre>
+<p>En este caso si hiciéramos cambios en alguna de las cabeceras <emb>.h</emb> make no recompilaría los códigos C <emb>.c</emb>. Si quisiéramos, como generalmente debería ser, que esto ocurriese:</p>
+<pre><code>CC=gcc
+CFLAGS=-I.
+DEPS = hola.h
+
+%.o: %.c $(DEPS)
+ $(CC) -c -o $@ $< $(CFLAGS)
+
+hola: hola.o
+ $(CC) -o hola hola.o</code></pre>
+<p>Podemos mejorar el makefile añadiéndole más acciones, como una acción \textit{clean} para limpiar la compilación.</p>
+<pre><code>CC=gcc
+CFLAGS=-I.
+DEPS = hola.h
+
+%.o: %.c $(DEPS)
+ $(CC) -c -o $@ $< $(CFLAGS)
+
+hola: hola.o
+ $(CC) -o hola hola.o
+
+clean:
+ rm -f hola hola.o</code></pre>
+<p>E incluso podemos hacerlo más genérico y escalable declarando los nombres de los ficheros en forma de variable:</p>
+<pre><code>CC=gcc
+CFLAGS=-I.
+DEPS = hola.h
+OBJ = hola.o
+
+%.o: %.c $(DEPS)
+ $(CC) -c -o $@ $< $(CFLAGS)
+
+hola: $(OBJ)
+ $(CC) -o $@ $^ $(CFLAGS)
+
+# Podemos usar .PHONY para indicarle a
+# make que el target clean en este caso
+# es ficticio y no debe crear fichero;
+# ya que si existiera un fichero llamado
+# clean en el directorio no trabajaria.
+.PHONY: clean
+clean:
+ rm -f $(ODIR)</code></pre>
+<p>Por otro lado, el <b>procedimiento CMake</b> (véase <a src="https://cmake.org">cmake.org</a>) o <i>Cross Platform Make</i> es una utilidad multiplataforma de automatización de código, que permite construir, probar y empaquetar el software. Es, en otras palabras, una suite de herramientas independientes de más alto nivel que make, y que facilita la compilación de programas C. Por ejemplo, para un fichero CMake <emb>CMakeList</emb>:</p>
+<pre><code># Version minima requerida
+cmake_minimum_required (VERSION 2.8)
+# Nombre del proyecto
+project (Hola)
+# Ficheros a agregar
+add_executable(hola hola.c)</code></pre>
+<p>Para ejecutar CMake simplemente llamamos a su comando propio seguido del fichero CMake: <emb>cmake CMakeList</emb>. La salida de este comando será un makefile.</p>
+</body>
+</html>
+\ No newline at end of file
diff --git a/programacion-c-punteros/index.html b/programacion-c-punteros/index.html
@@ -0,0 +1,67 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
+<meta name="viewport" content="width=device-width, initial-scale=1" />
+<title>De los punteros en el lenguaje C</title>
+<link rel="icon" type="image/png" href="/favicon.png" />
+<link rel="stylesheet" type="text/css" href="../article.css" />
+</head>
+<body>
+<header>
+<p class="title">De los punteros en el lenguaje C</p>
+<p class="date">24 de noviembre de 2018 • fjbalon</p>
+</header>
+<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>
+<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>
+<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>
+<img class="color-invertible" style="width: 300px;" src="punteros.png" />
+<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>
+<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>
+<pre><code>int i, j, *p;
+p = &i;
+*p = 10;
+p = &j;
+*p = -2;
+p = NULL;</code></pre>
+<p>Voy a tratar de explicar el código anterior:</p>
+<ol>
+<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>
+<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>
+<li><emb>*p = 10;</emb> asigna a la dirección de memoria a la que apunta <emb>p</emb> el valor 10.</li>
+<li><emb>p = &j;</emb> cambia el puntero a la variable <emb>j</emb>.</li>
+<li><emb>*p = -2;</emb> asigna dinámicamente a <emb>p</emb> el valor -2.</li>
+<li><emb>p = NULL;</emb> hace que el puntero ya no apunte a ninguna.</li>
+</ol>
+<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>
+<pre><code>int x = 1;
+float r = 1.0;
+
+void* ptr = &x;
+*(int *)ptr = 2;
+
+ptr = &r;
+*(float *) ptr = 1.1;</code></pre>
+<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>
+<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>
+<pre><code>int a, b, c;
+int *p1, *p2;
+void *p;
+
+p1 = &a;
+*p1 = 1;
+
+p2 = &b;
+*p2 = 2;
+
+p1 = p2;
+*p1 = 0;
+
+p2 = &c;
+*p2 = 3;
+
+p = &p1;
+*p = p2;
+*p1 = 1;</code></pre>
+</body>
+</html>
+\ No newline at end of file
diff --git a/programacion-c-punteros/punteros.png b/programacion-c-punteros/punteros.png
Binary files differ.