Skip to article frontmatterSkip to article content

Introducción a la programación en C

La sintaxis y programas básicos.

Introducción

Antes de iniciar el estudio de la programación en C, es fundamental comprender que programar no consiste únicamente en aprender un lenguaje, sino en desarrollar una forma de pensar. El lenguaje es la herramienta, pero el verdadero arte reside en la construcción de instrucciones lógicas para resolver problemas.

Programar es el acto de proporcionar instrucciones precisas a una computadora para que realice una tarea específica. Una diferencia clave con la comunicación humana es que la computadora no interpreta ambigüedades. No comprende conceptos como «más o menos». Cada paso debe estar perfectamente definido. En este sentido, C presenta ciertas ambigüedades que pueden conducir a resultados inesperados.

Durante la programación, la omisión de un solo detalle puede provocar que el programa no funcione. Por ello, es necesario aprender a pensar como una máquina, pero también a estructurar el pensamiento como un ser humano inteligente.

En C, no existen atajos, lo cual es una ventaja, ya que obliga a pensar de forma clara y lógica.

¿Por qué aprender C?

El lenguaje C fue creado en 1972 por Dennis Ritchie y Brian Kernighan en los Bell Labs. A pesar de tener más de 50 años de existencia, se sigue utilizando ampliamente debido a sus características fundamentales:

Características Principales de C

Nivel de Abstracción

Aunque C es considerado un lenguaje de nivel medio, en el momento en el que fue creado, era de «alto nivel», esto teniendo en cuenta la comparación con otros lenguajes y en particular, el Lenguaje Ensamblador.

Hoy en día y con el desarrollo de nuevos lenguajes, y teniendo en cuenta que pasaron solo 50 años de que fué creado, se lo sitúa en un nivel superior a los de bajo nivel, pero inferior a los que actualmente son considerados de alto nivel como Python o Java.

Esto le da un balance único:

Esta característica está ligada a que C es un lenguaje compilado. El código fuente se traduce directamente a código máquina antes de ejecutarse, a diferencia de los lenguajes interpretados (como Python) que son traducidos línea por línea en tiempo de ejecución.

Atributos Clave

Fortalezas y debilidades del lenguaje

Además de las razones para aprender y utilizar el lenguaje que están más arriba, hay un conjunto adicional de fortalezas importantes para tratar:

Acceso a conceptos de bajo nivel

Para ser utilizado como lenguaje de programación para sistemas, C provee acceso a conceptos directamente relacionados con el hardware que lo ejecutará. Conceptos como el tamaño en memoria, punteros, segmentos y las instrucciones son en definitiva muy similares a las que la computadora utiliza, de forma que los programas sean lo más rápidos posibles.

C es un lenguaje pequeño

El lenguaje provee un conjunto de instrucciones reducido; tengan en cuenta que el documento que define el lenguaje original, el K&R Segunda Edición, cubre el lenguaje completo en 49 páginas. Todo lo demás provisto por el lenguaje es cubierto con la librería estándar integrada implementada con funciones.

C es un lenguaje permisivo

El lenguaje asume que el programador sabe lo que está haciendo, por lo que permite hacer una mayor cantidad de cosas, para bien y para mal.

Debilidades

El lenguaje C, a pesar de su gran popularidad y potencia, presenta ciertas debilidades inherentes que deben ser comprendidas para un desarrollo eficiente y seguro. Es crucial conocer estas limitaciones desde su origen para establecer estrategias que las prevengan.

Estas surgen de la misma fuente que muchas de sus fortalezas: la cercanía del lenguaje C a la máquina. A continuación, algunas de sus debilidades más notorias

Los programas en C pueden ser propensos a errores

La flexibilidad de C lo convierte en un lenguaje propenso a errores. Los errores de programación que serían detectados en muchos otros lenguajes no pueden ser detectados por un compilador de C. En este aspecto, C es muy parecido al lenguaje ensamblador, donde la mayoría de los errores no se detectan hasta que el programa se ejecuta. Para empeorar las cosas, C contiene una serie de trampas para los desprevenidos. En las clases siguientes, veremos cómo un punto y coma extra puede crear un lazo infinito o un símbolo faltante puede causar que un programa falle.

Los programas en C pueden ser difíciles de entender

Aunque C es un lenguaje pequeño según la mayoría de las medidas, tiene una serie de características que no se encuentran en muchos lenguajes de programación (y que, en consecuencia, a menudo se malinterpretan). Estas características se pueden combinar de muchas maneras, muchas de las cuales, aunque obvias para el autor original de un programa, pueden ser difíciles de entender. Otro problema es la naturaleza concisa de los programas en C; fue diseñado en un momento en el que la comunicación interactiva con las computadoras era tediosa en el mejor de los casos. Como resultado, el lenguaje fue creado con propósito para ser conciso y minimizar el tiempo requerido para ingresar y editar programas. La flexibilidad de C también puede ser un factor negativo; los programadores que son demasiado inteligentes para su propio bien pueden hacer que los programas sean casi imposibles de entender.

Los programas en C pueden ser difíciles de modificar

Los programas grandes escritos en C pueden ser difíciles de cambiar si no han sido diseñados pensando en el mantenimiento. Los lenguajes de programación modernos suelen proporcionar características como clases y paquetes que soportan la división de un programa grande en piezas más manejables. C, desafortunadamente, carece de tales características.

Las herramientas del aprendiz

Instale lo justo y necesario

En Debian/Ubuntu,

sudo apt install build-essential

Para Windows, podés seguir la guía sobre la instalación del compilador.

Primer programa: el «Hola Mundo» al C

hola.c
1
2
3
4
5
6
7
#include <stdio.h>              // directiva al preprocesador

int main()                      // punto de entrada del programa
{                               // inicio de un bloque de código
    printf("Hola mundo C.\n");  // llamada a la instruccion de salida
    return 0;                   // finalización del programa
}                               // fin del bloque de código

Program 1:El indispensable Hola Mundo!

Compilación y Ejecución

Para ejecutar un programa en C, primero hay que compilarlo. Esto se hace desde la terminal con un compilador como gcc. Y aunque se verá y usará un entorno gráfico, la consola es el mínimo común denominador.

Proceso de compilación en C

Figure 1:El proceso de compilación transforma el código fuente en un ejecutable que la máquina puede ejecutar directamente. A diferencia de Python, C requiere este paso previo antes de la ejecución.

# Compila el archivo hola.c y crea un ejecutable llamado a.out
# (en Linux/macOS) o a.exe (en Windows)
$> gcc hola.c

# Ejecuta el programa
$> ./a.out
Hola mundo C.
$>

Program 2:La salida por la terminal.

Si se presta atención a la instrucción printf, se puede observar que faltan dos caracteres que están en el programa, pero no se ven en la salida. Esto es una secuencia de control, es la forma de ingresar caracteres que no son visibles, y el \n es el «enter» o salto de linea.

Pieza por pieza

  1. #include <stdio.h>: Es una directiva del preprocesador. Le indica al compilador que incluya la librería estándar de entrada/salida (stdio.h), que contiene la definición de la función printf.

  2. int main(): Es el punto de entrada del programa. Todo programa en C comienza su ejecución aquí. La palabra int indica que la función devolverá un número entero.

  3. { ... }: Las llaves definen un bloque de código. Todo lo que está dentro de las llaves pertenece a la función main.

  4. printf("Hola mundo C.\n");: Es una instrucción que llama a la función printf para imprimir el texto en la consola. \n es un carácter especial que representa un salto de línea.

  5. return 0;: Es la instrucción que finaliza la función main y devuelve un valor al sistema operativo. Por convención, 0 significa que el programa terminó sin errores.

  6. El código del ejemplo, hace uso de comentarios de línea para ayudar a ubicar la pieza específica que se describe en esta lista.

El Algoritmo: pensar antes de escribir

Mentalidad de programador

  1. Leé el problema. Comprendelo. Dibújalo.

  2. Divílo en pasos simples, para que una máquina sin intuición los pueda seguir.

  3. Usá papel y lápiz. No escribas código antes de tener claro el objetivo.

  4. Convertí esos pasos en instrucciones en C.

Roll Safe thinking

Pensar es más importante que escribir.

Ejemplo simple, pero clave: sumar dos números

  1. Leer un número.

  2. Leer otro número.

  3. Sumar.

  4. Mostrar el resultado.

#include <stdio.h>

int main()
{
    int a;
    int b;
    printf("Ingresá dos números: ");
    scanf("%d %d", &a, &b);
    printf("La suma es: %d\n", a + b);
    return 0;
}

Sobre las reglas de estilo

El uso de reglas de estilo en la programación en C, aunque a veces se percibe como una restricción, es fundamental para garantizar la consistencia y legibilidad del código. Al adherirse a un conjunto de normas, como las convenciones de nomenclatura, la indentación uniforme y la estructuración de comentarios, se facilita enormemente la colaboración entre desarrolladores y el mantenimiento del software a largo plazo. Incluso las reglas que pueden parecer controvertidas o arbitrarias, como la posición de las llaves o el uso de espacios en lugar de tabulaciones, tienen un propósito pedagógico. Obligan a los programadores a ser más conscientes de su estilo de escritura, promoviendo un aprendizaje más profundo sobre las mejores prácticas y la importancia de la uniformidad en el desarrollo de software. Esto eleva la calidad del código no solo en su funcionalidad, sino también en su estética y claridad. Para más detalles, consulte la regla Regla 0x0000h: La claridad y prolijidad son de máxima importancia.

Por otro lado, esto es parte del uso profesional del lenguaje, tanto que existen múltiples estándares de estilo.

C obfuscado

Incluso los fans más acérrimos del lenguaje están de acuerdo que el lenguaje puede volverse difícil de leer con bastante facilidad.

Esta «capacidad» del lenguaje se acentúa en la competencia anual de código C obfuscado IOCC, en la que se buscan las formas más rebuscadas posibles para crear programas que compilan y funcionan, pero de la forma más enrevesada posible.

El ganador en la categoría «El mejor de una línea» del 2019, Dave Burton, Contar palabras

e,n,j,o,y;main(){for(++o;n=-~getchar();e+=11==n,y++)o=n>0xe^012>n&&'`'^n^65?!n:!o?++j:o;printf("%8d%8d%8d\n",e^n,j+=!o&&y,y);}

Como se puede observar, el lenguaje se presta para crear código muy difícil de leer.

Sintaxis Básica

La sintaxis es el conjunto de reglas que definen cómo debe escribirse el código para ser considerado válido.

Mientras que la gramática determina si el código tiene sentido lógico y estructural. Es posible que algo sea sintácticamente válido pero gramaticalmente incorrecto.

Identificadores y Palabras Reservadas

Identificadores: Son los nombres que damos a variables y funciones. Deben empezar con una letra o un guion bajo (_) y pueden contener letras, números y guiones bajos. C distingue entre mayúsculas y minúsculas (suma es diferente de Suma).

Palabras Reservadas: Son palabras con un significado especial en C y no pueden ser usadas como identificadores (ej: int, if, else, while, return).

Ejemplos

Es importante tener en cuenta que hay una forma específica para cada tipo de identificador, esto lo iremos viendo a lo largo del curso y está resumido en las cuestiones de estilo (ver Regla 0x0001h: Los identificadores deben ser descriptivos).

Variables: las cajas

¿Qué son?

Una variable es un nombre simbólico para un espacio en memoria que guarda un valor. Pensalo como una caja con una etiqueta y un contenido que se puede cambiar.

Variables y memoria

Figure 3:Las variables son abstracciones sobre ubicaciones de memoria. Cada una tiene un nombre, un tipo, y ocupa un espacio específico en la RAM.

Tipos básicos en C

Tipos de datos en C

Figure 4:Vista general de los tipos de datos primitivos en C, sus tamaños en memoria, rangos de valores y especificadores de formato.

Declaración y asignación

int edad = 42;      // caja llamada edad, con 42 adentro
float pi = 3.14;    // caja llamada pi, con 3.14
char inicial = 'A'; // caja llamada inicial, con 'A'

Podés declarar y luego asignar:

int numero;
numero = 17;

¿Es necesario inicializar las variables?

Si se declara una variable, pero no se le asigna un valor inicial, su contenido es indeterminado: puede contener cualquier cosa, lo que se conoce como «basura». En sistemas operativos modernos, muchas veces la memoria se entrega inicializada en cero para evitar que se filtren datos de otros programas, pero no se puede confiar en esta inicialización por defecto.

A medida que el programa se ejecuta y reutiliza memoria, es posible que una variable sin inicializar contenga valores viejos, distintos de cero, o cualquier cosa inesperada. Por eso, siempre inicializá las variables antes de usarlas. Esto evita errores difíciles de detectar y hace el código más seguro y predecible.

Es en este punto donde entran en juego las reglas de estilo, como la Regla 0x0003h: Siempre debés inicializar las variables a un valor conocido.

¿Cómo funcionan?

Ejercicio 1

Solution to Exercise Valores
1
2
3
4
5
6
7
8
9
10
11
12
13
14
#include <stdio.h>

int main()
{
    int edad = 30;
    float altura = 1.75;
    char inicial = 'M';

    printf("Edad: %d\n", edad);
    printf("Altura: %.2f\n", altura);
    printf("Inicial: %c\n", inicial);

    return 0;
}

Un poco más de detalle

En C, cada expresión tiene un «valor» y, fundamentalmente, se clasifica en una de dos categorías: L-value o R-value. Esta distinción es crucial para entender cómo el compilador maneja los datos, las asignaciones de memoria y los diferentes roles de los identificadores en un programa.

L-Values

Un L-value (del inglés locator value o left value) representa a una variable en la memoria, el identificador en sí (la etiqueta de la caja).

Esta es una ubicación que se puede modificar, y donde se guardan los resultados de las expresiones derechas (R-Values). Por ejemplo, en la declaración int x = 10;, la variable x es un L-value. x se refiere a una ubicación de memoria específica donde se almacena el valor 10. Se puede modificar su valor, como en x = 20;.

R-Values

Un R-value (del inglés read value, ‘right’ value) es una expresión que representa un valor temporal o literal que no tiene una ubicación específica en la memoria.

Como su nombre indica, un R-value solo puede ser leído y, por lo tanto, solo puede aparecer en el lado derecho de un operador de asignación. No se puede asignar un nuevo valor a un R-value porque no hay un lugar garantizado en la memoria para almacenarlo.

Ejemplos comunes de R-values son los literales numéricos (como 10, 3.14), el resultado de una operación aritmética (a + b), o el valor de retorno de una función (mi_funcion()). Intentar asignar un valor a un R-value, como en 100 = x; o (a + b) = 5;, dará como resultado un error de compilación, ya que ni 100 ni el resultado de a + b son L-values con una dirección de memoria asignable.

Entrada y salida: hablar con el usuario

printf() - Mostrar resultados

Sirve para mostrar texto y valores como mensajes; puede consultar el apunte más detallado del tema.

printf("Tiene %d años\n", edad);

El par de símbolos \n se usan para indicar el ‘salto de línea’, para que no quede todo junto en una sola. Específicamente, cada vez que se ve una \, se indica que el siguiente carácter tiene un significado diferente del que se ve; esto se llama secuencias de escape.

Especificadores más comunes

TipoEspecificador
int%d
float%f
char%c
string%s (con char[])

scanf() - Leer datos desde el teclado

La función scanf() sirve para que el programa reciba datos del usuario. Es necesario indicar el tipo de dato y pasar a qué variable se le asignará el valor obtenido (más adelante se analizará el uso y significado del operador &).

int edad;
printf("Ingrese su edad: ");
scanf("%d", &edad);

Se usan los mismos códigos de formato que printf.

Ejercicio 2

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#include <stdio.h>

int main()
{
    char inicial;
    int edad;
    float nota;

    printf("Ingresá tu inicial: ");
    scanf(" %c", &inicial);  // espacio antes de %c para evitar problemas de buffer

    printf("Edad: ");
    scanf("%d", &edad);

    printf("Nota promedio: ");
    scanf("%f", &nota);

    printf("\nHola %c, tenés %d años y tu promedio es %.1f\n", inicial, edad, nota);

    return 0;
}

Condicionales, tomando decisiones

Las estructuras condicionales permiten que el programa tome decisiones.

Flujo de control con if/else

Figure 5:Diagrama de flujo mostrando cómo funcionan las estructuras condicionales: el programa evalúa condiciones secuencialmente y ejecuta el bloque correspondiente.

if, else if, else

if (condicion)
{
    // bloque si se cumple
} else if (otra_condicion)
{
    // otro camino
} else
{
    // camino por defecto
}

En donde las condiciones, deben ser el resultado de una expresión lógica.

Operadores lógicos comunes

Ejemplo

int edad;
scanf("%d", &edad);

if (edad >= 18)
{
    printf("Mayor de edad\n");
} else
{
    printf("Menor de edad\n");
}

Ejercicio 3

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#include <stdio.h>

int main()
{
    int nota;
    printf("Ingrese su nota: ");
    scanf("%d", &nota);

    if (nota >= 6)
    {
        printf("Promociona\n");
    } else if (nota >= 4)
    {
        printf("Aprueba\n");
    } else
    {
        printf("Desaprueba\n");
    }
}

Decisiones múltiples switch

Útil para comparar una variable con múltiples valores constantes. Tenga en cuenta que esta estructura solo compara igualdad, aunque se pueden agrupar.

switch (expresion)
{
    case valor1:
        // sentencias
        break;
    case valor2:
        // sentencias
        break;
    default:
        // sentencias si no coincide ningún caso
}

Es importante destacar que la instrucción break es opcional, y puede ser utilizada para agrupar «casos».

switch (x)
{
    case 1:
    case 2:
    case 3:
        printf("Entre 1 y 3\n");
        break;
    default:
        printf("Otro valor\n");
}

Lazos repetir hasta dominar el universo

Un lazo, o bucle, o loop es una estructura que permite repetir una o más instrucciones mientras se cumpla una condición. Esta es la forma en la que se le indica a la máquina: «hacé esto muchas veces sin que yo tenga que copiar y pegar»_.

Hay tres formas principales de lazos en C:

while — Repetición basada en condición

Las instrucciones del bloque contenido en el while se ejecutarán mientras la condición (i < 5) sea verdadera. Si nunca lo es, el bloque no se ejecuta.

int i = 0;
while (i < 5)
{
    printf("i vale %d\n", i);
    i = i + 1; // o i++
}

Flujo

Flujo del lazo while

Figure 6:Diagrama de flujo del lazo while: evalúa la condición, ejecuta el bloque si es verdadera, y repite hasta que la condición sea falsa.

Ejercicio 4

Solution to Exercise while #
1
2
3
4
5
6
7
8
9
10
11
12
#include <stdio.h>

int main()
{
    int i = 10;
    while (i >= 1)
    {
        printf("%d\n", i);
        i--;
    }
    return 0;
}

for — Lazos controlados por un contador

Este tipo de lazo es ideal cuando se sabe cuántas veces se quiere repetir. Aunque hace lo mismo que el while, este es más estructurado con secciones específicas para cada acción del lazo.

for (int i = 0; i < 5; i++)
{
    printf("i vale %d\n", i);
}

Y su equivalente con while:

int i = 0;                      // inicio
while (i < 5) {                 // condición
    printf("i vale %d\n", i);   // bloque
    i++;                        // paso
}

Ejercicio 5

Solution to Exercise for #
1
2
3
4
5
6
7
8
9
10
11
12
#include <stdio.h>

int main() {
    for (int i = 0; i <= 30; i++)
    {
        if (i % 3 == 0)
        {
            printf("%d es múltiplo de 3\n", i);
        }
    }
    return 0;
}

do...while — Ejecuta primero, pregunta después

Do, do while, do while if...

  • Rammstein, du...while

Ejemplo Grafico de lazos
int clave;
do {
    printf("Ingresá la clave (123): ");
    scanf("%d", &clave);
} while (clave != 123);

Este tipo de lazo garantiza al menos una ejecución. Ideal para menús o ingreso de datos que deben ejecutarse al menos una vez.

Flujo

Ejercicio 6

Solution to Exercise for #
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#include <stdio.h>

int main() {
    int clave;
    int clave_correcta = 1234; // Definimos una clave correcta

    do {
        printf("Ingresá la clave: ");
        scanf("%d", &clave);

        if (clave == clave_correcta) {
            printf("Acceso concedido. ¡Bienvenido!\n");
        } else {
            printf("Clave incorrecta. Intentá de nuevo.\n");
        }
    } while (clave != clave_correcta);

    return 0;
}

break y continue — Atajos dentro del ciclo

En C, break y continue son dos instrucciones de control que permiten modificar el flujo normal de un lazo. Aunque pueden resultar útiles en ciertos contextos, su uso abusivo o descontrolado puede reducir la claridad del código.

break

Sirve para salir completamente del lazo, sin importar si la condición sigue siendo verdadera.

for (int i = 1; i <= 10; i++) {
    if (i == 5) {
        break; // termina el lazo cuando i vale 5
    }
    printf("i = %d", i);
}

continue

Sirve para saltar al final del ciclo actual y seguir con la siguiente vuelta.

for (int i = 1; i <= 5; i++) {
    if (i == 3) {
        continue; // omite imprimir cuando i vale 3
    }
    printf("i = %d", i);
}

Ejercicio 7

Solution to Exercise break #
1
2
3
4
5
6
7
8
9
10
11
#include <stdio.h>

int main()
{
    int i;
    for (i = 0; i < 5; i++)
    {
        printf("valor actual: %d\n", i);
    }
    return 0;
}

Ejercicio 8

1
2
3
4
5
6
7
8
#include <stdio.h>

int main() {
    for (int i = 1; i <= 10; i = i + 2) {
        printf("i = %d\n", i);
    }
    return 0;
}

Lazos con bandera (flag)

En algunos casos, no es posible reescribir el lazo para que no utilice break, simplemente porque no hay una expresión que lo permita, o porque es necesario salir del lazo antes, por lo que es necesario aplicar una estrategia clásica en programación estructurada.

El uso de una variable bandera para controlar la repetición de un lazo. En lugar de usar break, se define una variable booleana que indica si se debe continuar o no.

Desde el estándar C99, se puede usar el tipo bool del encabezado stdbool.h, lo cual mejora la legibilidad.

Ejemplo:

#include <stdio.h>
#include <stdbool.h>

int main() {
    bool continuar = true;
    int numero;

    while (continuar) {
        printf("Ingresá un número (0 para salir): ");
        scanf("%d", &numero);

        if (numero == 0) {
            continuar = false; // apagamos la bandera
        } else {
            printf("Ingresaste: %d", numero);
        }
    }
    return 0;
}

Ventajas

Ejercicio 9

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
#include <stdio.h>
#include <stdbool.h> // Se necesita esta librería para usar 'bool'

int main()
{
    int clave;
    int clave_correcta = 1234; // Definimos la clave correcta
    bool acceso_concedido = false; // Nuestra bandera booleana

    // Usamos un lazo while y controlamos la salida con la bandera
    while (!acceso_concedido)
    {
        printf("Ingresá la clave: ");
        scanf("%d", &clave);

        if (clave == clave_correcta)
        {
            printf("Acceso concedido. ¡Bienvenido!\n");
            acceso_concedido = true; // Cambiamos la bandera para salir del lazo
        }
        else
        {
            printf("Clave incorrecta. Intentá de nuevo.\n");
        }
    }

    return 0;
}

Ejercicios

  1. Pida dos números y muestre el mayor.

  2. Muestre los números del 1 al 100.

  3. Sume los números pares del 1 al 100.

  4. Pida un número e indique si es primo.

  5. Pida una nota (0 a 10) e indique si aprobó.

  6. Haga un programa que pida la contraseña hasta que sea la correcta.

Pensar antes de escribir (otra vez)

Cuando estés atascado:

El compilador le dirá qué no entiende. Escúchelo, corrija e intentá nuevamente.

Zach Galifianakis doing math

No siga más allá (todavía)

No se adelante a las partes siguientes del apunte, a los referidos a funciones, punteros, structs ni arrays (aún).

Primero entendé lo esencial:

Ya vamos a ver...

¡Y algunas cosas más!

Afilando el código

Programar bien es:

“Escriba código que un colega pueda entender a las 3 AM.”

Bibliografía y Recursos Adicionales

Glosario

Lenguaje Ensamblador
El lenguaje ensamblador (assembly language) es un lenguaje de programación de bajo nivel que representa las instrucciones de código de máquina de una arquitectura de procesador específica mediante mnemónicos. Mantiene una correspondencia casi directa (a menudo uno a uno) con las operaciones del hardware. Requiere un programa llamado ensamblador (assembler) para traducir los mnemónicos al código de máquina ejecutable por el procesador. Ofrece control preciso sobre el hardware con una legibilidad superior a la del código máquina.
Lenguaje de Máquina
El lenguaje de máquina (machine language o machine code) es el conjunto de instrucciones en formato binario (secuencias de ceros y unos) que la unidad central de procesamiento (CPU) de una computadora puede ejecutar directamente. Es el nivel más bajo de lenguaje de programación, específico para cada arquitectura de procesador. Todas las formas de software deben ser traducidas o interpretadas a este lenguaje para poder ser ejecutadas por el hardware.

Conceptos Clave

Este apunte establece los fundamentos sintácticos y conceptuales de C, proporcionando las herramientas básicas para escribir programas simples pero completos.

Conexión con el Siguiente Tema

Hasta ahora escribimos programas lineales con datos individuales y control de flujo básico. Pero rápidamente surge la necesidad de organizar código más complejo: ¿cómo evitar repetir el mismo bloque de código 10 veces? ¿Cómo dividir un problema grande en partes manejables? ¿Cómo hacer que una solución sea reutilizable?

El próximo apunte, Funciones y descomposición funcional, introduce la descomposición funcional como mecanismo fundamental para estructurar programas. Las funciones permiten:

Con las estructuras de control que ya dominamos, las funciones se convierten en las “piezas de Lego” que ensamblamos para construir sistemas más sofisticados. El concepto de alcance (scope) que introduciremos es fundamental para entender cómo las funciones mantienen independencia y evitan interferencias no deseadas.

Pregunta puente: Si queremos calcular el área de 5 rectángulos diferentes, ¿tiene sentido escribir 5 veces el código base * altura? La respuesta natural nos lleva al concepto de función.

Referencias y Lecturas Complementarias

Textos Fundamentales

Recursos en Línea

Compiladores y Estándares

Herramientas de Desarrollo

References
  1. Kernighan, B. W., & Ritchie, D. M. (2014). C Programming Language, 2nd Edition.
  2. King, K. N. (2008). C Programming: A Modern Approach (2nd ed.). W. W. Norton & Company.
  3. Gustedt, J. (2019). Modern C. Manning Publications. https://modernc.gforge.inria.fr/