Compare commits

...

16 Commits

Author SHA1 Message Date
horacio 04be717bc7 ppdfviewer, basic, bits and string view 2026-11-14 00:15:02 -03:00
horacio c693541103 Refactor code structure for improved readability and maintainability 2026-11-12 15:27:39 -03:00
horacio 950a48b544 Add new PDF documentation for input devices 2026-11-12 14:42:02 -03:00
horacio 54ac3d140e Add DRM KMS documentation PDF to the distribution 2026-11-12 13:25:10 -03:00
horacio e2195a7ed2 Refactor code structure for improved readability and maintainability 2026-11-12 11:41:45 -03:00
horacio 913efb475b ejercicio de argchivos 2026-11-12 11:27:34 -03:00
horacio 361de2745c files 2026-11-06 10:28:14 -03:00
horacio 82008f51bf practica pipes3-5 2026-11-03 15:00:09 -03:00
horacio f4f56db493 agrego practicas 2026-10-31 11:14:30 -03:00
horacio 392cf493d1 Add 21-makefiles.pdf to the distribution directory 2026-10-24 14:58:40 -03:00
horacio 00441678a4 Add 13-getopt-long.pdf to the distribution 2026-10-24 13:33:59 -03:00
horacio 0177bbbceb Add GDB documentation PDF to distribution 2026-10-21 11:13:22 -03:00
horacio 64e8d471b5 Add 19-fechas.pdf to the distribution folder 2026-10-14 10:35:45 -03:00
horacio 187dd293e3 Add new PDF document for string view tutorial 2026-10-14 10:15:15 -03:00
horacio 9be881e043 Add new PDF document: 17-bits-y-mascaras.pdf 2026-10-14 00:08:47 -03:00
horacio e4a362a8fb Enhance Chapter 12 on Memory Alignment in Arenas
- Expanded section on memory alignment, clarifying the importance of data alignment for CPU efficiency.
- Introduced detailed explanations on type alignment versus data alignment.
- Added tables summarizing type sizes and alignments for clarity.
- Included step-by-step examples demonstrating struct alignment and padding.
- Revised code examples to reflect best practices for memory allocation and alignment.
- Updated PDF pagination to reflect the new content structure.
2026-10-13 23:46:24 -03:00
93 changed files with 21886 additions and 1457 deletions
+118
View File
@@ -262,3 +262,121 @@ Reglas de diseño (resumen):
> Si se modifica `assets/pdf/print.css`, hay que **regenerar todos** los capítulos para que ningún
> PDF quede con un diseño distinto.
---
## Protocolo de escritura de archivos extensos
Cuando el agente (humano o IA) necesita escribir un archivo Markdown de contenido grande
(≥ 600 líneas, como los capítulos del libro), **no usar una única llamada a `write` con todo el contenido**.
Los herramientas de escritura pasan el contenido dentro de un string JSON y los caracteres especiales
(tres backticks ```, `$`, `{`, `}`, `\`, comillas) pueden romper el parseo.
### Enfoque correcto (confirmado en producción)
1. **Escribir con `write` solo los primeros ~500-600 líneas**, hasta la primera sección completa
(hasta un `---` o final de una parte). El archivo se crea correctamente porque el contenido
es manejable para el parser JSON.
2. **Usar `edit` para ir agregando las secciones restantes**. Cada llamada a `edit` reemplaza
una cadena corta (`oldString`) por otra más larga (`newString`). La cadena a buscar es siempre
muy breve (ej: el último texto del archivo actual) y la cadena de reemplazo incluye la nueva sección.
```
oldString: "- [ ] Termina limpiamente al escribir \"exit\"." ← solo la última línea existente
newString: "- [ ] Termina limpiamente al escribir \"exit\".\n\n---\n# PARTE 5 — ..." ← misma + nueva sección
```
3. **Verificar el conteo de líneas** con un bash/PowerShell simple después de cada edit grande,
para confirmar que la sección se incorporó correctamente:
```
Get-Content book\22-file-descriptors.md | Measure-Object -Line
```
### Por qué fallaba el enfoque anterior
Un archivo de capítulo tiene ~1200-1500 líneas con:
- Bloques de código C con backticks triples (```` ```c ````) que el parser JSON confunde
- Strings con comillas escapadas (`\"`) que colisionan con las del string JSON
- Caracteres especiales como `$` en ejemplos de shell o `\n` en strings C
Con chunks de ≤ 600 líneas, el contenido cabe en un string JSON sin romper el parseo.
### Regla práctica
> **Nunca escribir más de 600 líneas de una sola vez con `write`.** Si el contenido total es mayor,
> usar `write` para la primera parte y `edit` sucesivo para el resto.
---
## 11. Corrección de caracteres malformados (mojibake)
Los capítulos en español pueden acumular **codificación doble**: bytes UTF-8 almacenados como si
fuera Latin-1/CP1252, lo que genera mojibake visible como `ú`, `Práctica` o caracteres
`\xef\xbf\xbd` (replacement char) en vez de "práctica". Esto pasa cuando el parser JSON del tool
de escritura corrompe los bytes multibyte.
### Cómo detectar
```python
import os
path = r"C:\Users\horacio\Desarrollo\c-programming\book\TU-CAPITULO.md"
with open(path, "rb") as f:
raw = f.read()
# Si hay bytes no ASCII pero el archivo se decodifica como UTF-8 bien formado,
# puede haber entidades HTML o caracteres dobles codificados.
try:
text = raw.decode("utf-8")
except UnicodeDecodeError:
print("NO es UTF-8 — hay corrupción de encoding")
# Buscar replacement char U+FFFD (EF BF BD)
if b"\xef\xbf\xbd" in raw:
print("Encontrado replacement char — el archivo tiene mojibake")
# Buscar entidades HTML sueltas (ú, é, ñ)
for ent in [b"ú", b"é", b"ñ", b"á", b"ó", b"ú"]:
if ent in raw:
print(f"Entidad HTML detectada: {ent}")
```
### Cómo corregir (reconstruir UTF-8 limpio)
Si el archivo está corrupto, **borrar y reconstruir** desde un script Python que escriba en
UTF-8 nativo. El pattern probado en producción es:
1. **Borrar el archivo corrupto.** No intentes repararlo con `edit` — si ya tiene entidades HTML
mezcladas con bytes dobles, la reparación parcial deja residuos.
2. **Escribir con un script Python que use `encoding='utf-8'`.** El script construye el contenido
como strings de Python (que son Unicode internos) y lo escribe como bytes UTF-8 limpios.
No uses `write` del agente para contenido > 600 líneas.
```python
# rebuild_chapter.py
chapter_file = r"C:\Users\horacio\Desarrollo\c-programming\book\25-drm-kms.md"
with open(chapter_file, "w", encoding="utf-8") as f:
f.write("# Capítulo 25 — DRM/KMS\n") # texto en Unicode → se escribe como UTF-8 limpio
```
3. **Si el contenido es largo**, dividí en chunks de ~250-300 líneas y uso `open(..., 'a')` para
append cada chunk al archivo ya creado.
4. **Verificar** que no queden caracteres corruptos:
```python
raw = open(path, "rb").read()
text = raw.decode("utf-8", errors="replace")
assert "\ufffd" not in text # sin replacement chars
for ent in [b"ú", b"é", b"ñ"]:
assert ent not in raw # sin entidades HTML sueltas
```
### Regla de prevención
> **Nunca pasar texto con acentos/ñ directamente en un string JSON `write`.** Si el contenido del
> capítulo tiene caracteres UTF-8 multibyte, escribirlo como un bloque grande en `write` puede
> corromper la codificación. La forma segura es: script Python que construya el Unicode interno y
> lo escriba con `encoding="utf-8"`.
+288 -13
View File
@@ -231,33 +231,308 @@ que lo vuelven "de producción".
### 12.4.1 Alineación de memoria
Los procesadores no leen cualquier dirección igual de rápido, y algunos **exigen** que ciertos tipos
empiecen en direcciones múltiplo de su tamaño (`int` a múltiplo de 4, `double` a múltiplo de 8, etc.).
Si repartís tamaños impares (por ejemplo 3 bytes), la próxima asignación puede quedar **desalineada**
y provocar comportamientos raros o lentitud.
#### Por qué a la CPU le importa dónde empieza un dato
La solución es **redondear el tamaño hacia arriba** hasta un múltiplo de la alineación:
Los procesadores no leen cualquier dirección igual de rápido, y algunos **exigen** que ciertos tipos
empiecen en direcciones "redondas". Si repartís tamaños impares (3 bytes, 5, 1...) el próximo dato
puede quedar **desalineado** y provocar lentitud o, en arquitecturas estrictas, un *crash*
(comportamiento indefinido).
Pero antes de seguir hay que desarmar una trampa de vocabulario, porque es la raíz de tu duda:
> **"Múltiplo de su tamaño" es un atajo que solo vale para los primitivos.** La regla de verdad es:
> cada tipo exige que su dirección sea **múltiplo de su ALINEACIÓN**, y la alineación **no siempre
> coincide con el tamaño**. Para `int`, `double` y `char` da igual; para un `struct`, casi nunca.
> Eso es exactamente lo que hace que te preguntes si podés mezclar tipos. Podés. Seguí leyendo.
#### La alineación es una propiedad del TIPO, no del dato ni de la arena
Una arena **no tiene tipo**: guarda bytes y no sabe qué vas a poner adentro. La alineación no es una
propiedad del valor ni de la arena: es una propiedad **del tipo** que vos vas a escribir en ese
hueco. El lenguaje ya sabe, para cada tipo, cuánto exige:
| Tipo | Tamaño | Alineación típica (x86-64) |
|------|:------:|:--------------------------:|
| `char` | 1 | 1 |
| `short` | 2 | 2 |
| `int` | 4 | 4 |
| `long`, `double`, puntero | 8 | 8 |
| `struct` | según sus miembros (con relleno) | **= la mayor alineación de sus miembros** |
#### La idea que te salva: UNA alineación para todos
Acá está la respuesta a tu primera pregunta. ¿Podés tener `int`, `char`, `double` y structs complejos
en la **misma** arena, bien alineados? **Sí, y no hace falta calcular nada por tipo.**
La clave: si **cada** bloque arranca en un múltiplo de 8, entonces arranca también en un múltiplo de
4, de 2 y de 1. Un múltiplo de 8 *es* múltiplo de todos los divisores de 8. Así que alineando
**todo** a 8 cubrís a la vez a `char` (1), `int` (4), `double`/puntero (8) y a cualquier struct cuya
alineación sea ≤ 8:
```text
base+0 base+8 base+16 base+24
| | | |
v v v v
[ double ][ int ][ char ][ struct ... ]
^8 ^8 ^8 ^8
todos múltiplos de 8 -> 8, 4, 2 y 1 quedan satisfechos
```
Por eso el ejemplo de `main` en 12.3 puede pedir un `Point` y después 100 `int` del mismo bloque: no
calculás la posición de nadie, **alineás cada reparto al mismo valor** y listo.
> **¿Qué alineación universal uso?** `8` alcanza para `int`, `double` y punteros. Para estar
> cubierto ante *cualquier* tipo (incluido algún SIMD o `long double`), usá
> `ARENA_ALIGN = _Alignof(max_align_t)` (normalmente 16). Es el valor que el estándar considera
> suficiente para todo. Un poquito más de desperdicio, cero dolores de cabeza.
#### Structs: por qué el tamaño NO te dice la alineación
Esta es la parte que confunde. Mirá:
```c
#define ARENA_ALIGN 8 // alineamos a 8 bytes
struct Mixed { char tag; int value; }; // sizeof = 8 | _Alignof = 4
struct Pair { double a; double b; }; // sizeof = 16 | _Alignof = 8
struct Quad { int a, b, c, d; }; // sizeof = 16 | _Alignof = 4
```
¿Por qué `Mixed` mide 8 y no 5? Porque el compilador **inserta 3 bytes de relleno** (*padding*)
después de `tag`, para que el `int` caiga alineado a 4. Y mide 8 (múltiplo de 4) para que, en un
arreglo `Mixed items[10]`, el `value` del segundo elemento también quede alineado.
De ahí sale el dato que te ahorra todo el cálculo:
> **La alineación de un tipo SIEMPRE divide a su tamaño.** Es una garantía del estándar de C, y
> existe precisamente para que los arreglos funcionen. Consecuencia directa: si alineás el bloque a
> la alineación del struct, **todos** sus miembros caen alineados solos. Nunca tenés que ubicar
> `tag` ni `value` a mano.
Entonces, tu pregunta "¿cómo calculo, en base al `sizeof`, la posición que debe ocupar un struct
complejo?" tiene una respuesta incómoda y liberadora: **no lo calcules desde el `sizeof`.** El
`sizeof` te dice *cuánto ocupa*, no *dónde tiene que empezar*. Para saber eso, pedile la alineación
al lenguaje:
- `_Alignof(Type)` (C11) te da la alineación en bytes.
- `alignof(Type)` con `<stdalign.h>` (el alias con nombre lindo).
- `_Alignas(16)` en una variable te fuerza *su* alineación.
> **Cuidado con el `sizeof` como fuente de alineación.** `struct Pair` (size 16) pide 8, no 16;
> `struct Quad` (size 16) pide 4, no 16. Si asumís "alineo a `sizeof`" vas a desperdiciar y, peor,
> a equivocarte con structs de tamaño impar (p. ej. size 24 con align 8). La alineación y el tamaño
> son primos hermanos, no gemelos.
#### Ejemplo paso a paso: alineación y tamaño de un struct
Vamos con un caso completo, miembro por miembro:
```c
struct Record {
int a; // 4 bytes
int b; // 4 bytes
double c; // 8 bytes
char d; // 1 byte
};
```
**Paso 1 — la alineación de cada miembro.** En x86/x64, lo habitual es:
| Miembro | Tipo | `_Alignof` |
|:-------:|:----:|:----------:|
| `a` | `int` | 4 |
| `b` | `int` | 4 |
| `c` | `double` | 8 |
| `d` | `char` | 1 |
**Paso 2 — la alineación del struct.** Es la **regla del mayor**: el alineamiento de una estructura
es el mayor alineamiento de entre todos sus miembros.
```text
max(4, 4, 8, 1) = 8
```
Por lo tanto `_Alignof(struct Record)` es **8**.
**Paso 3 — acomodar los miembros (y el relleno).** El compilador ubica cada miembro en el primer
offset que sea múltiplo de *su* alineación:
| Miembro | Alineación | Offset donde cae | Ocupa |
|:-------:|:----------:|:----------------:|:-----:|
| `a` | 4 | 0 | 0..3 |
| `b` | 4 | 4 | 4..7 |
| `c` | 8 | 8 | 8..15 |
| `d` | 1 | 16 | 16 |
| *relleno final* | — | 17 | 17..23 (7 bytes) |
Byte a byte queda así:
```text
offset 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |17 ... 23
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+----------+
| a (int) | b (int) | c (double) | d | relleno |
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+----------+
align ^4 ^4 ^8 ^1
```
- `b` termina en 8 y `c` pide 8: **entra directo, sin relleno interno**.
- `d` ocupa 1 byte (offset 16), pero el struct completo tiene que medir un múltiplo de 8.
**Paso 4 — el `sizeof`.** Contenido real: `4 + 4 + 8 + 1 = 17`. Para que sea múltiplo de 8, se agregan
**7 bytes de relleno al final**:
```text
sizeof(struct Record) = 17 + 7 = 24
```
> **La trampa del relleno final.** El `sizeof` **no** es la suma de los miembros: incluye el relleno.
> Acá `4 + 4 + 8 + 1 = 17`, pero `sizeof` es **24**, no 16. Esos 7 bytes "fantasma" existen para que,
> en un arreglo `struct Record items[7]`, cada elemento arranque alineado a 8. Si te olvidás del
> relleno final, el número no cierra.
#### `_Alignof`: ¿operador, macro o función?
`_Alignof` **no es una función** (no se llama en runtime, no existe un símbolo con ese nombre) y
**tampoco es, en sí mismo, una macro**. Es un **operador unario**, igual que `sizeof`:
- Lleva el guión bajo (`_Alignof`) porque en C11 entró como **palabra clave reservada**: los
identificadores con `_` + mayúscula están reservados al lenguaje, así no choca con código viejo.
- Se evalúa en **tiempo de compilación** y produce un valor de tipo `size_t` (la cantidad de bytes de
alineación).
- Su operando es un **tipo** entre paréntesis (`_Alignof(double)`, `_Alignof(struct Record)`), **no**
una variable.
- El `_` inicial es feo a propósito. Por eso `<stdalign.h>` define el **macro** `alignof`, que se
expande a `_Alignof`. Ahí está tu respuesta fina: `alignof` **es** un macro; `_Alignof` es la
palabra clave. En C23 `alignof` pasó a ser palabra clave por derecho propio (y el macro se jubiló).
Cómo usarlo:
```c
#include <stdio.h>
#include <stdalign.h> // trae el macro `alignof`
typedef struct { int a; int b; double c; char d; } Record;
int main(void) {
printf("sizeof(int) = %zu\n", sizeof(int)); // 4
printf("alignof(double) = %zu\n", alignof(double)); // 8
printf("sizeof(Record) = %zu\n", sizeof(Record)); // 24
printf("alignof(Record) = %zu\n", alignof(Record)); // 8
return 0;
}
```
> **Detalle de `printf`.** `_Alignof` y `sizeof` devuelven `size_t`: imprimilos con `%zu`, no con
> `%d` (si no, el formato no coincide con el tipo y tenés *undefined behavior*).
> **Para la arena.** Este es el número que le pasás a `ARENA_ALIGN`: `_Alignof(max_align_t)` cubre
> cualquier tipo; `_Alignof(Record)` alcanza para los `Record`. Lo importante: la alineación se
> **lee del tipo**, no se adivina desde el `sizeof`.
#### La fórmula, para tontos
El corazón de todo es redondear **hacia arriba** al múltiplo más cercano:
```c
#define ARENA_ALIGN 8 // alineamos a 8 bytes (potencia de 2)
// Redondea n hacia arriba al múltiplo de ARENA_ALIGN más cercano.
#define ARENA_ALIGN_UP(n) (((n) + (ARENA_ALIGN - 1)) & ~(size_t)(ARENA_ALIGN - 1))
```
La parte `& ~(ARENA_ALIGN - 1)` parece magia negra, pero es solo aritmética de bits. Vamos despacio,
con `A = 8`:
1. **`A - 1 = 7 = 0b0111`.** Es una máscara con los **3 bits de abajo** en 1. Esos 3 bits son justo
los que "sobran" dentro de un bloque de 8 (los números 0..7).
2. **`n + (A - 1)` = `n + 7`.** Sumar 7 "empuja" el número hacia arriba lo suficiente para que,
cualquiera sea su resto dentro del bloque de 8, cruce al próximo límite. Si ya estaba justo en un
límite, el `+7` se queda adentro del mismo bloque y da lo mismo.
3. **`~(A - 1) = ~0b0111 = 0b...11111000`.** El `~` invierte: ahora esos 3 bits bajos están en 0 y el
resto en 1. Hacer `&` con esto **borra el resto**, deja los bits altos intactos.
4. **Resultado:** el mayor múltiplo de 8 que es ≤ `n+7`, o sea el **menor múltiplo de 8 ≥ `n`**.
Tabla, con bits de 4 para que se vea:
| `n` | `n + 7` | `n + 7` en binario | `& ~7` | resultado |
|:---:|:-------:|:------------------:|:------:|:---------:|
| 0 | 7 | `0111` | `0000` | **0** |
| 1 | 8 | `1000` | `1000` | **8** |
| 7 | 14 | `1110` | `1000` | **8** |
| 8 | 15 | `1111` | `1000` | **8** |
| 9 | 16 | `1 0000` | `1 0000` | **16** |
Ahí está toda la fórmula: **sumar `A-1` y borrar los bits bajos con `~`**. Nada más.
> **¿Por qué solo sirve con potencias de 2?** Porque `~(A-1)` solo "borra exactamente los bits del
> resto" cuando `A` es potencia de 2. Para `A = 10` esa máscara no existe y habría que dividir con
> `/` y `%`. Por suerte **todas** las alineaciones estándar son potencias de 2 (1, 2, 4, 8, 16...),
> así que el truco siempre aplica.
#### Aplicala a la posición, no al tamaño (variante robusta)
El capítulo redondea el **tamaño** y da por hecho que `offset` ya estaba alineado. Eso alcanza
mientras el bloque base esté alineado y todos pidan lo mismo. La versión más honesta **redondea el
cursor antes de repartir**, que es lo que de verdad querés: que el hueco *nuevo* empiece alineado.
```c
void *arena_alloc(Arena *a, size_t size) {
size_t aligned = ARENA_ALIGN_UP(size); // reservamos un poco más, para alinear
if (a->offset + aligned > a->capacity) {
// Subo el cursor del offset al múltiplo de 8 más cercano ...
size_t aligned = ARENA_ALIGN_UP(a->offset);
// ... y recién ahí veo si entra el pedido exacto.
if (aligned + size > a->capacity) {
return NULL;
}
void *ptr = a->buffer + a->offset;
a->offset += aligned;
void *ptr = a->buffer + aligned; // puntero al hueco ya alineado
a->offset = aligned + size; // el cursor queda donde termina el dato
return ptr;
}
```
La parte `& ~(ARENA_ALIGN - 1)` es un truco de bits: como 8 es potencia de 2, "redondear hacia
arriba a múltiplo de 8" se hace con una máscara. Es válido **solo porque la alineación es potencia
de 2**.
Diferencia con la versión anterior (la del capítulo, que redondea el tamaño): esta **desperdicia
menos** (usa `size` exacto y solo paga el *padding* necesario antes del bloque) y expresa mejor la
idea "alineá la **dirección** donde arranca el dato".
#### Ojo: el bloque base también manda
Todo lo anterior asume que `a->buffer` es múltiplo de 8. Como el puntero que devolvés es
`base + offset`, si `base` está torcido, **todo** queda torcido y alinear el offset no sirve de nada.
- `malloc` **garantiza** la alineación de cualquier tipo, así que un bloque pedido con `malloc` es
seguro.
- En cambio un `unsigned char buffer[4096];` local **puede** quedar alineado a 1, ¡aunque el array
sea grande! Si vas a prestar memoria (ejercicio 12.11), forzá la alineación o, mejor, alineá la
**dirección absoluta**, que se banca hasta una base torcida:
```c
#include <stdint.h> // uintptr_t
void *arena_alloc(Arena *a, size_t size) {
// Alineo la DIRECCIÓN real (base + offset), no solo el offset.
uintptr_t start = (uintptr_t)(a->buffer + a->offset);
uintptr_t aligned = (start + (ARENA_ALIGN - 1)) & ~(uintptr_t)(ARENA_ALIGN - 1);
size_t pad = aligned - start; // los bytes que "sacrifico" para alinear
if (a->offset + pad + size > a->capacity) {
return NULL;
}
a->offset += pad + size;
return (void *)aligned;
}
```
Ese `pad = aligned - start` **es** la respuesta literal a "cómo calculo la posición que debe
ocupar": la posición es `aligned`, y el costo de alinear es `pad`. Simple y sin depender de que
`base` haya venido alineado.
#### Lo que te llevás de alineación
- La alineación es del **tipo**, no del valor ni de la arena.
- Para mezclar tipos **no** calculás posiciones: elegís **una** alineación universal
(`_Alignof(max_align_t)`) y alineás cada reparto. Un múltiplo de 8 ya es múltiplo de 8, 4, 2 y 1.
- La alineación de un struct = la mayor de sus miembros, y **siempre divide a su `sizeof`**. Si el
bloque arranca alineado, los miembros caen alineados solos.
- La fórmula es `(n + A - 1) & ~(A - 1)`, y solo funciona con `A` potencia de 2.
- El bloque **base** también tiene que estar alineado; lo más robusto es alinear la dirección
absoluta, no solo el offset.
### 12.4.2 ¿Y si no entra lo que pedís?
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
+1405
View File
File diff suppressed because it is too large Load Diff
+3778
View File
File diff suppressed because it is too large Load Diff
+1808
View File
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
+1077
View File
File diff suppressed because it is too large Load Diff
+1162
View File
File diff suppressed because it is too large Load Diff
+2704
View File
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
Binary file not shown.
+143
View File
@@ -0,0 +1,143 @@
#include "arena.h"
#include <string.h>
char* arena_strdup(Arena* ref_arena, const char* s){
char* str = (char*) arena_alloc(ref_arena, strlen(s) + 1);
if(str == NULL){
return NULL;
}
strcpy(str, s);
return str;
}
void* arena_chunk_alloc(Arena* ref_arena, Chunk* chunk, size_t s){
size_t aligned = (chunk->offset + (ARENA_MEMORY_ALIGN - 1)) & ~(ARENA_MEMORY_ALIGN -1);
if ((aligned + s <= chunk->size)){
chunk->offset = aligned;
void* start = (void *)(chunk->buffer + chunk->offset);
chunk->offset = aligned + s;
return start;
}
return NULL;
}
Chunk* arena_chunk_create(size_t s){
printf("Creating a new chunk of %zu bytes\n", s);
Chunk* chunk1 = (Chunk*)malloc(sizeof(Chunk));
if(chunk1 == NULL){
return NULL;
}
chunk1->size = s;
chunk1->offset = 0;
chunk1->next = NULL;
chunk1->buffer = (unsigned char *)malloc(s);
if(chunk1->buffer == NULL){
perror("Error creando chunk...\n");
free(chunk1);
chunk1 = NULL;
return NULL;
}
printf("Chunk creado correctamente\n");
return chunk1;
}
void arena_chunk_free(Chunk* chunk){
printf("Liberando %zu bytes de memoria\n", chunk->size);
if(chunk->buffer != NULL){
free(chunk->buffer);
chunk->buffer = NULL;
}
free(chunk);
}
void* arena_alloc(Arena* ref_arena, size_t s){
if(ref_arena == NULL){
return NULL;
}
if(ref_arena->current == NULL){
return NULL;
}
Chunk* current_chunk = ref_arena->current;
void* ptr = arena_chunk_alloc(ref_arena, current_chunk, s);
if(ptr == NULL){
size_t new_size = current_chunk->size * 2;
if(new_size < s){
new_size = s;
}
Chunk *new_chunk = arena_chunk_create(new_size);
if(new_chunk == NULL){
return NULL;
}
current_chunk->next = new_chunk;
new_chunk->next = NULL;
ref_arena->current = new_chunk;
return arena_alloc(ref_arena, s);
}
return ptr;
}
Arena arena_create(size_t s){
Arena new_arena = {
.current = NULL,
.first = NULL
};
Chunk* chunk1 = arena_chunk_create(s);
if(chunk1 == NULL){
perror("Error creando arena\n");
exit(1);
}
new_arena.current = chunk1;
new_arena.first = chunk1;
printf("Arena creada correctamente\n");
return new_arena;
}
void arena_free(Arena* ref_arena){
Chunk* item = ref_arena->first;
while (item != NULL) {
Chunk *next = item->next;
arena_chunk_free(item);
item = next;
}
ref_arena->first = NULL;
ref_arena->current = NULL;
printf("Arena liberada\n");
}
void arena_print(Arena* ref_arena){
printf("ARENA INFO\n");
printf("==========\n");
printf("first: %p\n", ref_arena->first);
printf("next: %p\n", ref_arena->current);
printf("==========\n");
}
+29
View File
@@ -0,0 +1,29 @@
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#define ARENA_MEMORY_ALIGN 8
typedef struct Chunk{
size_t size;
size_t offset;
unsigned char *buffer;
struct Chunk *next;
}Chunk;
typedef struct{
Chunk *current;
Chunk *first;
}Arena;
Arena arena_create(size_t);
void* arena_alloc(Arena*, size_t);
void arena_free(Arena*);
void arena_print(Arena*);
Chunk* arena_chunk_create(size_t);
void arena_chunk_free(Chunk*);
void* arena_chunk_alloc(Arena*, Chunk*, size_t);
char* arena_strdup(Arena*, const char*);
+90
View File
@@ -0,0 +1,90 @@
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
typedef struct{
unsigned char *buffer;
size_t size;
size_t offset;
}Arena;
Arena arena_create(size_t);
void* arena_alloc(Arena *, size_t);
void arena_destroy(Arena *);
int main(void){
Arena arena = arena_create(13);
int *ptrInt1 = (int*)arena_alloc(&arena, sizeof(int));
int *ptrInt2 = (int*)arena_alloc(&arena, sizeof(int));
float *ptrFloat1 = (float*)arena_alloc(&arena, sizeof(float));
char *ptrChar1 = (char*)arena_alloc(&arena, sizeof(char));
int need = sizeof(int)*2 + sizeof(float) + sizeof(char);
printf("sizeof int: %d\n", (int)sizeof(int));
printf("sizeof float: %d\n", (int)sizeof(float));
printf("sizeof char: %d\n", (int)sizeof(char));
printf("Necesitamos: %d\n", need);
if(ptrInt1 != NULL){
*ptrInt1 = 18;
printf("Primer entero: %d\n", *ptrInt1);
}
if(ptrInt2 != NULL){
*ptrInt2 = 27;
printf("Segundo entero: %d\n", *ptrInt2);
}
if(ptrFloat1 != NULL){
*ptrFloat1 = 3.1415f;
printf("Primer flotante: %f\n", *ptrFloat1);
}
if(ptrChar1 != NULL){
*ptrChar1 = 'L';
printf("Primer char: %c\n", *ptrChar1);
}
arena_destroy(&arena);
return 0;
}
Arena arena_create( size_t bytes){
Arena new_arena = {
.buffer = NULL,
.size = bytes,
.offset = 0
};
new_arena.buffer = (unsigned char *)malloc(bytes);
if(new_arena.buffer == NULL){
perror("Error asignando memoria");
exit(1);
}
return new_arena;
}
void* arena_alloc(Arena *ref_arena, size_t bytes){
if(ref_arena->buffer == NULL){
return NULL;
}
if(ref_arena->offset + bytes > ref_arena->size){
perror("Memoria llena\n");
return NULL;
}
void* ptr_ref = ref_arena->buffer + ref_arena->offset;
ref_arena->offset += bytes;
return ptr_ref;
}
void arena_destroy(Arena *ref_arena){
if(ref_arena->buffer != NULL){
free(ref_arena->buffer);
ref_arena->buffer = NULL;
}
}
BIN
View File
Binary file not shown.
+82
View File
@@ -0,0 +1,82 @@
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#define FPS 10
typedef struct{
unsigned char *buffer;
size_t size;
size_t offset;
}Arena;
Arena arena_create(size_t);
void* arena_alloc(Arena *, size_t);
void arena_reset(Arena *);
void arena_destroy(Arena *);
int main(void){
srand(time(NULL));
Arena arena = arena_create(100);
for(int i=0; i < FPS; i++){
int* ptrLeft = arena_alloc(&arena, sizeof(int));
if(ptrLeft != NULL){
*ptrLeft = rand()%FPS;
printf("El datos del frame es: %d\n", *ptrLeft);
}
arena_reset(&arena);
}
arena_destroy(&arena);
return 0;
}
Arena arena_create( size_t bytes){
Arena new_arena = {
.buffer = NULL,
.size = bytes,
.offset = 0
};
new_arena.buffer = (unsigned char *)malloc(bytes);
if(new_arena.buffer == NULL){
perror("Error asignando memoria");
exit(1);
}
return new_arena;
}
void* arena_alloc(Arena *ref_arena, size_t bytes){
if(ref_arena->buffer == NULL){
return NULL;
}
if(ref_arena->offset + bytes > ref_arena->size){
perror("Memoria llena\n");
return NULL;
}
void* ptr_ref = ref_arena->buffer + ref_arena->offset;
ref_arena->offset += bytes;
return ptr_ref;
}
void arena_reset(Arena *ref_arena){
ref_arena->offset = 0;
}
void arena_destroy(Arena *ref_arena){
if(ref_arena->buffer != NULL){
free(ref_arena->buffer);
ref_arena->buffer = NULL;
}
}
BIN
View File
Binary file not shown.
+106
View File
@@ -0,0 +1,106 @@
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#define FPS 10
#define ARENA_ALIGN 8
#define ALLOC_TYPE(REF, TYPE) (TYPE*)arena_alloc(&REF, sizeof(TYPE))
typedef struct{
unsigned char *buffer;
size_t size;
size_t offset;
}Arena;
Arena arena_create(size_t);
void* arena_alloc(Arena *, size_t);
void arena_reset(Arena *);
void arena_destroy(Arena *);
bool arena_is_aligned(size_t);
int main(void){
Arena arena = arena_create(32);
int *test = ALLOC_TYPE(arena, int);
*test = 5;
arena_alloc(&arena, 3);
arena_alloc(&arena, 1);
arena_alloc(&arena, 5);
arena_alloc(&arena, 9);
arena_alloc(&arena, 8);
arena_alloc(&arena, 1);
arena_destroy(&arena);
return 0;
}
bool arena_is_aligned(size_t pos){
size_t mask = 7;
return (pos & mask) == 0;
}
Arena arena_create( size_t bytes){
Arena new_arena = {
.buffer = NULL,
.size = bytes,
.offset = 0
};
new_arena.buffer = (unsigned char *)malloc(bytes);
if(new_arena.buffer == NULL){
perror("Error asignando memoria");
exit(1);
}
return new_arena;
}
void* arena_alloc(Arena *ref_arena, size_t bytes){
if(ref_arena->buffer == NULL){
return NULL;
}
size_t aligned = ((ref_arena->offset + (size_t)((ARENA_ALIGN - 1))) & ~(ARENA_ALIGN - 1));
if(aligned + bytes > ref_arena->size){
printf("arena_alloc(%d): NULL \n", (int) bytes);
return NULL;
}
void* ptr_ref = ref_arena->buffer + aligned;
printf("arena_alloc(%d) ", (int) bytes);
if(arena_is_aligned((size_t)ptr_ref)){
printf("aligned: true ");
}else{
printf("aligned: false ");
}
printf(" base + %d", (int)aligned);
printf(" offset: %d -> %d \n", (int)ref_arena->offset, (int)aligned);
ref_arena->offset = aligned + bytes;
return ptr_ref;
}
void arena_reset(Arena *ref_arena){
ref_arena->offset = 0;
}
void arena_destroy(Arena *ref_arena){
if(ref_arena->buffer != NULL){
free(ref_arena->buffer);
ref_arena->buffer = NULL;
}
}
BIN
View File
Binary file not shown.
+107
View File
@@ -0,0 +1,107 @@
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <string.h>
#define ARENA_ALIGN 8
typedef struct{
unsigned char *buffer;
size_t size;
size_t offset;
}Arena;
Arena arena_create(size_t);
void* arena_alloc(Arena *, size_t);
void arena_reset(Arena *);
void arena_destroy(Arena *);
bool arena_is_aligned(size_t);
char* arena_strdup(Arena*, const char *);
int main(void){
Arena arena = arena_create(16);
char* s1 = arena_strdup(&arena, "arena");
char* s2 = arena_strdup(&arena, "hola");
char* s3 = arena_strdup(&arena, "x");
arena_destroy(&arena);
return 0;
}
char* arena_strdup(Arena* ref_arena, const char *src){
char* ref_str = (char*) arena_alloc(ref_arena, strlen(src) + 1);
if(ref_str == NULL){
perror("No se ha podido reservar memoria para la cadena.");
return NULL;
}
strcpy(ref_str, src);
return ref_str;
}
bool arena_is_aligned(size_t pos){
size_t mask = 7;
return (pos & mask) == 0;
}
Arena arena_create( size_t bytes){
Arena new_arena = {
.buffer = NULL,
.size = bytes,
.offset = 0
};
new_arena.buffer = (unsigned char *)malloc(bytes);
if(new_arena.buffer == NULL){
perror("Error asignando memoria");
exit(1);
}
return new_arena;
}
void* arena_alloc(Arena *ref_arena, size_t bytes){
if(ref_arena->buffer == NULL){
return NULL;
}
size_t aligned = ((ref_arena->offset + (size_t)((ARENA_ALIGN - 1))) & ~(ARENA_ALIGN - 1));
if(aligned + bytes > ref_arena->size){
printf("arena_alloc(%d): NULL \n", (int) bytes);
return NULL;
}
void* ptr_ref = ref_arena->buffer + aligned;
printf("arena_alloc(%d) ", (int) bytes);
if(arena_is_aligned((size_t)ptr_ref)){
printf("aligned: true ");
}else{
printf("aligned: false ");
}
printf(" base + %d", (int)aligned);
printf(" offset: %d -> %d \n", (int)ref_arena->offset, (int)aligned);
ref_arena->offset = aligned + bytes;
return ptr_ref;
}
void arena_reset(Arena *ref_arena){
ref_arena->offset = 0;
}
void arena_destroy(Arena *ref_arena){
if(ref_arena->buffer != NULL){
free(ref_arena->buffer);
ref_arena->buffer = NULL;
}
}
BIN
View File
Binary file not shown.
+120
View File
@@ -0,0 +1,120 @@
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <string.h>
#define ARENA_ALIGN 8
typedef struct{
unsigned char *buffer;
size_t size;
size_t offset;
}Arena;
Arena arena_create(size_t);
void* arena_alloc(Arena *, size_t);
void arena_reset(Arena *);
void arena_destroy(Arena *);
bool arena_is_aligned(size_t);
size_t arena_checkpoint(Arena*);
void arena_restore(Arena*, size_t);
int main(void){
Arena arena = arena_create(32);
size_t cp0 = arena_checkpoint(&arena);
int* x = (int*)arena_alloc(&arena, 8);
*x = 21;
arena_alloc(&arena, 8);
size_t cp1 = arena_checkpoint(&arena);
int* tmp = (int*)arena_alloc(&arena, 8);
arena_restore(&arena, cp1);
printf("x:%d\n", *x);
arena_alloc(&arena, 16);
arena_restore(&arena, cp0);
arena_alloc(&arena, 32);
arena_destroy(&arena);
return 0;
}
void arena_restore(Arena* ref_arena, size_t chk){
ref_arena->offset = chk;
}
size_t arena_checkpoint(Arena* ref_arena){
return ref_arena->offset;
}
bool arena_is_aligned(size_t pos){
size_t mask = 7;
return (pos & mask) == 0;
}
Arena arena_create( size_t bytes){
Arena new_arena = {
.buffer = NULL,
.size = bytes,
.offset = 0
};
new_arena.buffer = (unsigned char *)malloc(bytes);
if(new_arena.buffer == NULL){
perror("Error asignando memoria");
exit(1);
}
return new_arena;
}
void* arena_alloc(Arena *ref_arena, size_t bytes){
if(ref_arena->buffer == NULL){
return NULL;
}
size_t aligned = ((ref_arena->offset + (size_t)((ARENA_ALIGN - 1))) & ~(ARENA_ALIGN - 1));
if(aligned + bytes > ref_arena->size){
printf("arena_alloc(%d): NULL \n", (int) bytes);
return NULL;
}
void* ptr_ref = ref_arena->buffer + aligned;
printf("arena_alloc(%d) ", (int) bytes);
if(arena_is_aligned((size_t)ptr_ref)){
printf("aligned: true ");
}else{
printf("aligned: false ");
}
printf(" base + %d", (int)aligned);
printf(" offset: %d -> %d \n", (int)ref_arena->offset, (int)aligned);
ref_arena->offset = aligned + bytes;
return ptr_ref;
}
void arena_reset(Arena *ref_arena){
ref_arena->offset = 0;
}
void arena_destroy(Arena *ref_arena){
if(ref_arena->buffer != NULL){
free(ref_arena->buffer);
ref_arena->buffer = NULL;
}
}
BIN
View File
Binary file not shown.
+178
View File
@@ -0,0 +1,178 @@
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#define ARENA_MEMORY_ALIGN 8
typedef struct Chunk{
size_t size;
size_t offset;
unsigned char *buffer;
struct Chunk *next;
}Chunk;
typedef struct{
Chunk *current;
Chunk *first;
}Arena;
Arena arena_create(size_t);
void* arena_alloc(Arena*, size_t);
void arena_free(Arena*);
void arena_print(Arena*);
Chunk* arena_chunk_create(size_t);
void arena_chunk_free(Chunk*);
void* arena_chunk_alloc(Arena*, Chunk*, size_t);
int main(void){
Arena arena = arena_create(32);
arena_print(&arena);
arena_alloc(&arena, 100);
arena_print(&arena);
arena_alloc(&arena, 40);
arena_print(&arena);
arena_free(&arena);
arena_print(&arena);
return 0;
}
void* arena_chunk_alloc(Arena* ref_arena, Chunk* chunk, size_t s){
size_t aligned = (chunk->offset + (ARENA_MEMORY_ALIGN - 1)) & ~(ARENA_MEMORY_ALIGN -1);
if ((aligned + s <= chunk->size)){
chunk->offset = aligned;
void* start = (void *)(chunk->buffer + chunk->offset);
chunk->offset = aligned + s;
return start;
}
return NULL;
}
Chunk* arena_chunk_create(size_t s){
printf("Creating a new chunk of %zu bytes\n", s);
Chunk* chunk1 = (Chunk*)malloc(sizeof(Chunk));
if(chunk1 == NULL){
return NULL;
}
chunk1->size = s;
chunk1->offset = 0;
chunk1->next = NULL;
chunk1->buffer = (unsigned char *)malloc(s);
if(chunk1->buffer == NULL){
perror("Error creando chunk...\n");
free(chunk1);
chunk1 = NULL;
return NULL;
}
printf("Chunk creado correctamente\n");
return chunk1;
}
void arena_chunk_free(Chunk* chunk){
printf("Liberando %zu bytes de memoria\n", chunk->size);
if(chunk->buffer != NULL){
free(chunk->buffer);
chunk->buffer = NULL;
}
free(chunk);
}
void* arena_alloc(Arena* ref_arena, size_t s){
if(ref_arena == NULL){
return NULL;
}
if(ref_arena->current == NULL){
return NULL;
}
Chunk* current_chunk = ref_arena->current;
void* ptr = arena_chunk_alloc(ref_arena, current_chunk, s);
if(ptr == NULL){
size_t new_size = current_chunk->size * 2;
if(new_size < s){
new_size = s;
}
Chunk *new_chunk = arena_chunk_create(new_size);
if(new_chunk == NULL){
return NULL;
}
current_chunk->next = new_chunk;
new_chunk->next = NULL;
ref_arena->current = new_chunk;
return arena_alloc(ref_arena, s);
}
return ptr;
}
Arena arena_create(size_t s){
Arena new_arena = {
.current = NULL,
.first = NULL
};
Chunk* chunk1 = arena_chunk_create(s);
if(chunk1 == NULL){
perror("Error creando arena\n");
exit(1);
}
new_arena.current = chunk1;
new_arena.first = chunk1;
printf("Arena creada correctamente\n");
return new_arena;
}
void arena_free(Arena* ref_arena){
Chunk* item = ref_arena->first;
while (item != NULL) {
Chunk *next = item->next;
arena_chunk_free(item);
item = next;
}
ref_arena->first = NULL;
ref_arena->current = NULL;
printf("Arena liberada\n");
}
void arena_print(Arena* ref_arena){
printf("ARENA INFO\n");
printf("==========\n");
printf("first: %p\n", ref_arena->first);
printf("next: %p\n", ref_arena->current);
printf("==========\n");
}
BIN
View File
Binary file not shown.
+86
View File
@@ -0,0 +1,86 @@
#include <stdio.h>
#include "../arena-lib/arena.h"
#include <string.h>
typedef struct Persona{
char* nombre;
int edad;
struct Persona* next;
}Persona;
void print_persona(Persona*);
int main(void){
printf("Alinacion struct Persona: %d\n", (int)_Alignof(Persona));
printf("sizeof struct Persona: %d\n", (int)sizeof(Persona));
Arena arena = arena_create(32);
char continuar = 'S';
Persona* first = NULL;
Persona* last = NULL;
do{
char input_name[50];
printf("Nombre:");
if (fgets(input_name, sizeof(input_name), stdin) != NULL) {
input_name[strcspn(input_name, "\n")] = '\0';
}
int input_edad = 0;
printf("Edad:");
scanf("%d", &input_edad);
printf("\n");
int c;
while ((c = getchar()) != '\n' && c != EOF);
Persona* p = (Persona*)arena_alloc(&arena, sizeof(Persona));
if(p == NULL){
perror("Ha ocurrido un error\n");
exit(1);
}
p->nombre = arena_strdup(&arena, input_name);
p->edad = input_edad;
p->next = NULL;
if(first == NULL){
first = p;
}
if(last != NULL){
last->next = p;
}
last = p;
printf("Cargar mas personas? (S) Continuar, (N): Terminar :");
scanf(" %c", &continuar);
while ((c = getchar()) != '\n' && c != EOF);
}while((continuar == 'S') || (continuar == 's'));
printf("Listado de personas cargadas:\n");
printf("=============================\n");
Persona* current = first;
while(current != NULL){
print_persona(current);
current = current->next;
}
arena_free(&arena);
return 0;
}
void print_persona(Persona* ref_persona) {
printf("%s: tiene %d years\n", ref_persona->nombre, ref_persona->edad);
}
BIN
View File
Binary file not shown.
+102
View File
@@ -0,0 +1,102 @@
#include "../arena-lib/arena.h"
#include <stdio.h>
typedef enum {
BIN_OP_SUMA,
BIN_OP_RESTA,
BIN_OP_MULTIPLY,
BIN_OP_DIVISION
} BinaryOps;
typedef enum {
NODE_NUMBER,
NODE_OPERATION
} NodeKind;
typedef struct Node{
union {
BinaryOps operation;
int number;
}value;
NodeKind type;
struct Node* left;
struct Node* right;
} Node;
Node* create_number(Arena* arena_ref, int n){
Node* node = (Node*)arena_alloc(arena_ref, sizeof(Node));
if(node == NULL){
return NULL;
}
node->type = NODE_NUMBER;
node->value.number = n;
node->left = NULL;
node->right = NULL;
return node;
}
Node* create_operation(Arena* ref_arena, BinaryOps op, Node* l, Node* r){
Node* node = (Node*)arena_alloc(ref_arena, sizeof(Node));
if(node == NULL){
return NULL;
}
node->type = NODE_OPERATION;
node->value.operation = op;
node->left = l;
node->right = r;
return node;
}
int node_compute(Node* node){
if(node->type == NODE_OPERATION){
int r1 = node_compute(node->left);
int r2 = node_compute(node->right);
int result = 0;
switch (node->value.operation) {
case BIN_OP_SUMA:
result = r1 + r2;
break;
case BIN_OP_RESTA:
result = r1 - r2;
break;
case BIN_OP_MULTIPLY:
result = r1 * r2;
break;
case BIN_OP_DIVISION:
result = (r2 != 0) ? r1 / r2 : 0;
break;
default:
result = 0;
break;
}
return result;
}
return node->value.number;
}
int main(void){
Arena arena = arena_create(32);
printf("Memory struct information\n");
printf("=========================\n");
printf("sizeof(Node):%zu\n", sizeof(Node));
printf("align(Node): %zu\n", _Alignof(Node));
//Creamos el arbol para 3 + (4 - 1)
Node* t1 = create_number(&arena, 3);
Node* t21 = create_number(&arena, 4);
Node* t22 = create_number(&arena, 1);
Node* t2 = create_operation(&arena, BIN_OP_RESTA, t21, t22);
Node* root = create_operation(&arena, BIN_OP_SUMA, t1, t2);
printf("Node compute\n");
printf("============\n");
printf("result: %d\n", node_compute(root));
arena_free(&arena);
return 0;
}
BIN
View File
Binary file not shown.
+73
View File
@@ -0,0 +1,73 @@
#include <limits.h>
#include <errno.h>
#include<stdio.h>
#include <stdlib.h>
#include<unistd.h>
#include<getopt.h>
static struct option option_args[] = {
{"help", no_argument, 0, 'h' },
{"verbose", no_argument, 0, 'v' },
{"output", required_argument, 0, 'o' },
{"max", required_argument, 0, 'm' },
{0,0,0,0}
};
void print_usage(char* arg){
fprintf(stdout, "Uso: %s\n", arg);
fprintf(stdout, "[--help]\n");
fprintf(stdout, "[--verbose]\n");
fprintf(stdout, "[--output <archivo>]\n");
fprintf(stdout, "[--max <num>]\n");
fprintf(stdout, "[posicionales...]\n");
}
int main(int argc, char* argv[]){
printf("argv[0]: %s\n", argv[0]);
int opt;
int opt_index = 0;
while((opt = getopt_long(argc, argv, "hvo:m:", option_args, &opt_index)) != -1){
switch (opt){
case 'h':
print_usage(argv[0]);
exit(0);
break;
case 'v':
fprintf(stdout, "Modo verbose: ON\n");
break;
case 'o':
fprintf(stdout, "Output: %s\n", optarg);
break;
case 'm':
errno = 0;
char* errorptr = NULL;
long maximo = strtol(optarg, &errorptr, 10);
if( (errno == EINVAL)
|| (errno == ERANGE)
|| (*errorptr != 0)
|| (maximo < INT_MIN)
|| (maximo > INT_MAX)
){
fprintf(stderr, "--max debe ser un numero entero valido.\n");
exit(1);
}
printf("Maximo:%ld\n", maximo);
break;
case '?':
print_usage(argv[0]);
exit(1);
break;
}
}
fprintf(stdout, "Posicionales:\n");
for(int i = optind; i < argc; i++){
fprintf(stdout, "%s\n", argv[i]);
}
return 0;
}
BIN
View File
Binary file not shown.
Executable
BIN
View File
Binary file not shown.
+60
View File
@@ -0,0 +1,60 @@
/*
* Enunciado del Ejercicio: Modificación de Arreglos mediante Aritmética de Punteros
*
* Objetivo:
* Practicar el manejo de punteros y su relación con los arreglos estáticos en el lenguaje C,
* aplicando aritmética de punteros para recorrer y modificar los elementos almacenados en memoria.
*
* Descripción:
*
* Escribe un programa completo en C que realice las siguientes tareas:
*
* Declaración e Inicialización:
*
* Declara un arreglo estático de 5 enteros (int) e inicialízalo
* con valores arbitrarios de tu elección (por ejemplo: 5, 10, 15, 20, 25).
*
* Declara un puntero a entero (int *ptr) que apunte al inicio del arreglo.
*
* Procesamiento con Aritmética de Punteros:
*
* Utiliza un bucle (for o el de tu preferencia) para recorrer el arreglo únicamente mediante
* aritmética de punteros y el operador de indirección en la forma *(ptr + i) (o incrementando el puntero directamente).
*
* Dentro del bucle, suma 10 al valor actual almacenado en cada posición del arreglo.
*
* Salida por Consola:
*
* Muestra en pantalla los valores del arreglo antes y después de aplicar la modificación
* para verificar que el cambio se realizó correctamente en la memoria del arreglo original.
*
* Restricciones:
*
* Está prohibido utilizar la notación de corchetes (arreglo[i]) para acceder o modificar
* los elementos del arreglo dentro del bucle. Debes usar estrictamente la sintaxis de punteros (*(ptr + i)).
*/
#include <stdio.h>
#define V_LENGTH 5
void print_arr(int *);
int main(void){
int v1[V_LENGTH] = {5, 10, 15, 20, 25};
int* ptr_v1 = v1;
print_arr(ptr_v1);
for(int i=0; i<V_LENGTH; i++){
*(ptr_v1 + i) += 10;
}
print_arr(ptr_v1);
return 0;
}
void print_arr(int *arr){
printf("Array: ");
for(int i = 0; i < V_LENGTH; i++){
printf(" %d,", *(arr + i));
}
printf("\n");
}
BIN
View File
Binary file not shown.
BIN
View File
Binary file not shown.
+25
View File
@@ -0,0 +1,25 @@
#include <stdio.h>
int main(void) {
unsigned char flags = 0b0000010;
unsigned char FLAG_A = 1u << 0;
unsigned char FLAG_B = 1u << 1;
printf("El FLAG_A es: %08b\n", FLAG_A);
printf("El FLAG_B es: %08b\n", FLAG_B);
// encender ambos.
flags = (FLAG_A | FLAG_B);
if (flags & (FLAG_A)) {
printf("El flag A esta encendido\n");
}
if (flags & (FLAG_B)) {
printf("El flag B esta encendido\n");
}
return 0;
}
+25
View File
@@ -0,0 +1,25 @@
/*
* El objetivo es escribir un codigo donde falle al intentar modificar el contenido de un puntero
* y tambien falle al intentar modificar a donde apunta otro puntero.
*/
int main(void){
int sensor_temp = 25;
int sensor_humedad = 60;
int ipa = 192;
int ipb = 168;
const int *ptr_lectura = &sensor_temp;
int * const ptr_config = &ipa;
ptr_lectura = &sensor_humedad;
//No debo poder modificar el valor del sensor mediante el puntero.
*ptr_lectura = 44;
*ptr_config = 10;
//No debo poder cambiar a donde apunta el puntero ptr_config.
ptr_config = &ipb;
return 0;
}
BIN
View File
Binary file not shown.
+3
View File
@@ -0,0 +1,3 @@
Hola, mundo
C es genial
Fin
+50
View File
@@ -0,0 +1,50 @@
#include <stdio.h>
#include <string.h>
int count_chars(char *rline);
void fix_path(char *rpath);
int main(void) {
char file_path[128];
int char_count = 0, lines_count = 0;
FILE *fp;
printf("Path:");
if (fgets(file_path, 128, stdin) == NULL) {
perror("fgets");
return 1;
}
printf("\nLeyendo archivo: %s", file_path);
fix_path(file_path);
fp = fopen(file_path, "r");
if (fp == NULL) {
perror("fopen");
return 1;
}
char lbuffer[256];
while ((fgets(lbuffer, 256, fp)) != NULL) {
char_count += count_chars(lbuffer);
lines_count++;
}
printf("Caracteres: %d\n", char_count);
printf("Lineas: %d\n", lines_count);
return 0;
}
int count_chars(char *rline) { return strlen(rline) - 1; }
void fix_path(char *rpath) {
for (int i = 0; i < 128; i++) {
if (rpath[i] == '\n') {
rpath[i] = '\0';
return;
}
}
}
BIN
View File
Binary file not shown.
+3
View File
@@ -0,0 +1,3 @@
ESTE ES UN ARCHIVO
DE PRUEBAS DONDE VAMOS A EVALUAR COMO
SE COPIA ESTE CORREO HORACIODRS@GMAIL.COM
+44
View File
@@ -0,0 +1,44 @@
#include <ctype.h>
#include <stdio.h>
#include <string.h>
int main(int argc, char *argv[]) {
char *src = "src-test.txt";
char *dst = "dst-test.txt";
if (argc == 3) {
src = strdup(argv[1]);
dst = strdup(argv[2]);
} else {
fprintf(stderr, "Argumentos invalidos.\n");
return 1;
}
FILE *fpsrc, *fpdst;
fpsrc = fopen(src, "r");
if (fpsrc == NULL) {
perror("fopen");
return 1;
}
fpdst = fopen(dst, "w");
if (fpdst == NULL) {
perror("fopen");
return 1;
}
int c;
while ((c = fgetc(fpsrc)) && c != EOF) {
fputc(toupper(c), fpdst);
}
fclose(fpsrc);
fclose(fpdst);
printf("Archivo duplicado en mayusculas con exito en: %s\n", dst);
return 0;
}
+3
View File
@@ -0,0 +1,3 @@
Este es un archivo
de pruebas donde vamos a evaluar como
se copia este correo horaciodrs@gmail.com
Binary file not shown.
+166
View File
@@ -0,0 +1,166 @@
#include <SDL2/SDL.h>
#include <SDL2/SDL_error.h>
#include <SDL2/SDL_events.h>
#include <SDL2/SDL_log.h>
#include <SDL2/SDL_render.h>
#include <SDL2/SDL_video.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void render_image(SDL_Renderer *ref_renderer, unsigned char *data,
unsigned long w, unsigned long h);
int main(int argc, char *argv[]) {
if (argc < 2) {
fprintf(stderr, "Argumentos invalidos\n");
return 1;
}
char *fname;
fname = strdup(argv[1]);
if (fname == NULL) {
perror("strdup");
return 1;
}
FILE *pfile = fopen(fname, "rb");
if (pfile == NULL) {
perror("fopen");
fclose(pfile);
return 1;
}
uint8_t *header = NULL;
header = malloc(sizeof(uint8_t) * 3);
printf("El sizeof de header es: %d\n", (int)sizeof(header));
if (fread(header, sizeof(uint8_t) * 2, 1, pfile) == 0) {
perror("fread");
fclose(pfile);
return 1;
}
header[3] = '\0';
int w, h, s;
if (fscanf(pfile, " %d %d %d", &w, &h, &s) != 3) {
fprintf(stderr, "Error leyendo las caracteristicas de la imagen.\n");
fclose(pfile);
return 1;
}
fprintf(stdout, "Header readed: %s\n", (unsigned char *)header);
fprintf(stdout,
"Las dimensiones son %dx%d pixeles y una escala maxima de color de "
"%d\n",
w, h, s);
// consumo un caracter mas y queda listo para leer los datos de los pixeles.
fgetc(pfile);
unsigned char *data = NULL;
unsigned long pixel_count = w * h;
data = malloc(sizeof(data) * pixel_count * 3);
if (data == NULL) {
perror("malloc");
fclose(pfile);
return 1;
}
unsigned long readed =
fread(data, sizeof(unsigned char) * 3, pixel_count, pfile);
fprintf(stdout, "%zu pixeles leidos de %zu\n", readed, pixel_count);
if (readed != pixel_count) {
fprintf(stderr, "Error leyendo datos del archivo\n");
free(data);
fclose(pfile);
}
if (SDL_Init(SDL_INIT_VIDEO) < 0) {
perror("SLD_Init");
free(data);
fclose(pfile);
return 1;
}
SDL_Window *window =
SDL_CreateWindow("Visor de imagenes", SDL_WINDOWPOS_CENTERED,
SDL_WINDOWPOS_CENTERED, w, h, SDL_WINDOW_SHOWN);
if (window == NULL) {
SDL_Log("SLD_WINDOW: %s", SDL_GetError());
SDL_Quit();
free(data);
fclose(pfile);
return 1;
}
SDL_Renderer *renderer = SDL_CreateRenderer(
window, -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC);
if (!renderer) {
SDL_Log("No se pudo crear el renderizador: %s", SDL_GetError());
SDL_DestroyWindow(window);
SDL_Quit();
free(data);
fclose(pfile);
return 1;
}
bool running = true;
SDL_Event ev;
while (running) {
while (SDL_PollEvent(&ev)) {
if (ev.type == SDL_QUIT) {
running = 0; // Si hacen clic en la "X", salimos
}
if (ev.type == SDL_KEYDOWN) {
// Si presionan Escape, salimos
if (ev.key.keysym.sym == SDLK_ESCAPE) {
running = 0;
}
}
}
SDL_RenderClear(renderer);
render_image(renderer, data, w, h);
SDL_RenderPresent(renderer);
}
SDL_DestroyRenderer(renderer);
SDL_DestroyWindow(window);
SDL_Quit();
free(data);
fclose(pfile);
return 0;
}
void render_image(SDL_Renderer *ref_renderer, unsigned char *rdata,
unsigned long int w, unsigned long h) {
unsigned long offset = 0;
for (unsigned long cury = 0; cury < h; cury++) {
for (unsigned long curx = 0; curx < w; curx++) {
uint8_t r = *(rdata + offset++);
uint8_t g = *(rdata + offset++);
uint8_t b = *(rdata + offset++);
SDL_SetRenderDrawColor(ref_renderer, r, g, b, 255);
SDL_RenderDrawPoint(ref_renderer, curx, cury);
}
}
}
BIN
View File
Binary file not shown.
+4
View File
@@ -0,0 +1,4 @@
Se encontraron 3 registros invalidos.
Iniciando reporte.
Procesando 128 registros.
Reporte generado correctamente.
+1
View File
@@ -0,0 +1 @@
Se encontraron 3 registros invalidos.
+7
View File
@@ -0,0 +1,7 @@
Permissions Size User Date Modified Name
.rw-r--r-- 38 horacio 28 Oct 10:58 errores.txt
.rw-r--r-- 0 horacio 28 Oct 11:07 listado.txt
.rw-r--r-- 271 horacio 28 Oct 10:55 main.c
.rwxr-xr-x 16k horacio 28 Oct 10:56 programa
.rw-r--r-- 24 horacio 28 Oct 11:04 salida.txt
.rw-r--r-- 19 horacio 28 Oct 11:00 test.txt
+9
View File
@@ -0,0 +1,9 @@
#include <stdio.h>
int main(void){
fprintf(stdout, "Iniciando reporte.\n");
fprintf(stdout, "Procesando 128 registros.\n");
fprintf(stdout, "Reporte generado correctamente.\n");
fprintf(stderr, "Se encontraron 3 registros invalidos.\n");
return 1;
}
BIN
View File
Binary file not shown.
+3
View File
@@ -0,0 +1,3 @@
Iniciando reporte.
Procesando 128 registros.
Reporte generado correctamente.
+2
View File
@@ -0,0 +1,2 @@
test
segunda linea
+16
View File
@@ -0,0 +1,16 @@
#include <stdio.h>
int main(void){
int c, count = 0, countbr = 0;
while((c = getchar()) != EOF){
if(c == '\n'){
countbr++;
}
count++;
}
fprintf(stdout, "Se leyeron %d bytes\n", count);
fprintf(stdout, "Se leyeron %d <br> \n", countbr);
return 0;
}
BIN
View File
Binary file not shown.
+2
View File
@@ -0,0 +1,2 @@
este es un archivo
de texto
+42
View File
@@ -0,0 +1,42 @@
#include <stdbool.h>
#include <stdio.h>
#include <string.h>
int count_words(char*);
int main(void){
char buffer[50];
int total_words = 0;
while((fgets(buffer, sizeof(buffer), stdin)) != NULL){
total_words += count_words(buffer);
}
printf("El total de palabras es: %d\n", total_words);
return 0;
}
int count_words(char* line){
int palabras = 0;
bool hay_espacio = false;
printf("line: %s", line);
if((line[0] != ' ') && strlen(line) > 0){
palabras++;
}
for(int i = 0; i < strlen(line); i++){
if(line[i] == ' '){
hay_espacio = true;
}
if((line[i] != ' ') && (line[i] != '\n') && (hay_espacio)){
palabras++;
hay_espacio = false;
}
}
return palabras;
}
BIN
View File
Binary file not shown.
+32
View File
@@ -0,0 +1,32 @@
#include <stdio.h>
void clear_buffer(void);
int main(void) {
int edad = 0;
char buffer[20];
printf("Ingresar una edad:");
scanf("%d", &edad);
clear_buffer();
printf("\nIngresar un nombre:");
fgets(buffer, 20, stdin);
printf("\n====================================\n");
printf("La edad ingresada es: %d \n", edad);
printf("El nombre ingresado es: %s \n", buffer);
return 0;
}
void clear_buffer(void) {
int c = 0;
while ((c = getchar()) && c != '\n' && c != EOF) {
}
}
BIN
View File
Binary file not shown.
+50
View File
@@ -0,0 +1,50 @@
#include <stdio.h>
typedef struct Document {
int id;
char active;
char name[50];
} Document;
void leer_id(Document *);
void leer_nombre(Document *);
void imprimir(Document *);
int main(void) {
Document hdr;
leer_id(&hdr);
leer_nombre(&hdr);
imprimir(&hdr);
return 0;
}
void leer_id(Document *ref) {
int rid = -1;
char c;
char ractive = 'n';
printf("Entrada:");
scanf("%d", &rid);
ref->id = rid;
while ((c = getchar()) && c != '\n' && c != EOF) {
if ((c == 's') || (c == 'S')) {
ractive = 's';
}
}
ref->active = ractive;
printf("\n");
}
void leer_nombre(Document *ref) {
printf("Nombre:");
fgets(ref->name, 50, stdin);
}
void imprimir(Document *ref) {
printf("=======================================\n");
printf("ID: %d \n", ref->id);
printf("ACTIVE: %c \n", ref->active);
printf("NOMBRE: %s \n", ref->name);
}
BIN
View File
Binary file not shown.
+13
View File
@@ -0,0 +1,13 @@
#include "stringv.h"
#include <stdio.h>
int main(void) {
StringView s1 = sv_from_cstr("Hola mundo con string view");
StringView s2 = sv_from_cstr("😊");
StringView last = sv_right(&s1, 4);
printf("El string view contiene: %s\n", s2.text);
printf("El length es: %zu\n", s2.lenght);
printf("last tiene:%.*s\n", (int)last.lenght, last.text);
return 0;
}
BIN
View File
Binary file not shown.
+60
View File
@@ -0,0 +1,60 @@
#include "stringv.h"
#include <stddef.h>
#include <stdio.h>
#include <string.h>
/*
* @brief Create a string view from a const char* and set their lenght
*
* @details This string view provides a view of a string. It does not allocate
* memory, therefore, it lives only while the source is alive. The
* lenght is a bytes number of the string. It does not represents the number of
* characters.
*
* @param str pointer from the original string. It can be NULL.
*
* @return a StringView with the view of original string with corresponding
* lenght.
*/
#define STRING_VIEW_NULL (StringView){.text = NULL, .lenght = 0}
StringView sv_from_cstr(const char *str) {
if (str == NULL) {
return STRING_VIEW_NULL;
}
return (StringView){.text = (char *)str, .lenght = strlen(str)};
}
StringView sv_left(const StringView *sv, size_t l) {
if (sv == NULL) {
perror("sv_left: pointer is NULL\n");
return STRING_VIEW_NULL;
}
if (sv->text == NULL) {
perror("sv_left: text pointer is NULL\n");
return STRING_VIEW_NULL;
}
if (sv->lenght < l) {
perror("sv_left: text length is less than specified length\n");
return STRING_VIEW_NULL;
}
return (StringView){.text = sv->text, .lenght = l};
}
StringView sv_right(const StringView *sv, size_t r) {
if (sv == NULL) {
perror("sv_right: pointer is NULL\n");
return STRING_VIEW_NULL;
}
if (sv->text == NULL) {
perror("sv_right: text pointer is NULL\n");
return STRING_VIEW_NULL;
}
if (sv->lenght < r) {
perror("sv_right: text length is less than specified length\n");
return STRING_VIEW_NULL;
}
size_t nlength = sv->lenght - r;
return (StringView){.text = sv->text + nlength, .lenght = r};
}
+14
View File
@@ -0,0 +1,14 @@
#ifndef STRING_VIEW_H
#define STRING_VIEW_H
#include <stddef.h>
typedef struct StringView {
char *text;
size_t lenght;
} StringView;
StringView sv_from_cstr(const char *);
StringView sv_left(const StringView *sv, size_t l);
StringView sv_right(const StringView *sv, size_t l);
#endif
+69
View File
@@ -0,0 +1,69 @@
/*
* EJERCICIO DE LENGUAJE C: STRUCTS Y PUNTEROS
*
* 1. Define una struct llamada Coordenada que contenga dos campos enteros: x e y.
* 2. Implementa una función constructora llamada Coordenada* crear_coordenada(int x, int y) que:
* - Reserve memoria dinámicamente utilizando malloc para una nueva estructura Coordenada.
* - Verifique si la reserva de memoria fue exitosa.
* - Inicialice sus campos x e y con los valores pasados como parámetros.
* - Devuelva el puntero a la estructura creada.
* 3. En la función main:
* - Utiliza la función constructora para crear una coordenada.
* - Muestra por pantalla los valores iniciales utilizando el operador flecha (->).
* - Modifica los valores de los campos de la estructura utilizando también el operador flecha (->).
* - Muestra los nuevos valores por pantalla.
* - Libera la memoria reservada dinámicamente utilizando free para evitar pérdidas de memoria.
*/
#include <stdio.h>
#include <stdlib.h>
typedef struct{
int x;
int y;
}Coordenada;
Coordenada* crear_coordenada(int x, int y);
void modificar_coordenada(Coordenada**, int x, int y);
void imprimir_coordenada(Coordenada**);
int main(void){
Coordenada* cord = crear_coordenada(10, 20);
imprimir_coordenada(&cord);
modificar_coordenada(&cord, 30, 40);
imprimir_coordenada(&cord);
free(cord);
return 0;
}
Coordenada* crear_coordenada(int x, int y){
Coordenada* new_cord = malloc(sizeof(Coordenada));
if(new_cord == NULL){
perror("No se pudo crear la coordenada\n");
exit(1);
}
new_cord->x = x;
new_cord->y = y;
return new_cord;
}
void modificar_coordenada(Coordenada** cord_address, int x, int y){
if((*cord_address) == NULL){
perror("No se ha proporcionado una coordenada para modificar\n");
exit(1);
}
(*cord_address)->x = x;
(*cord_address)->y = y;
}
void imprimir_coordenada(Coordenada** a){
printf("Coordenada(%d, %d);\n", (*a)->x, (*a)->y);
}
BIN
View File
Binary file not shown.
+92
View File
@@ -0,0 +1,92 @@
/*******************************************************************************
* TRABAJO PRÁCTICO / EJERCICIO INTEGRADOR: GESTIÓN DE PUNTEROS Y ESTRUCTURAS
*
* OBJETIVO:
* El propósito de este ejercicio es consolidar el manejo de estructuras,
* aritmética de punteros, indirección y diseño de funciones conpaso por referencia
* en el lenguaje C, evitando el uso de código resuelto y enfocándose en la
* especificación formal del problema.
*
* CONSIGNA:
* Desarrolle un programa en Lenguaje C que cumpla rigurosamente con los
* siguientes requerimientos técnicos y estructurales:
*
* 1. Definición del Tipo de Dato (Struct con Punteros Internos):
* - Defina una estructura denominada `Persona` que contenga dos campos:
* * Un puntero a caracteres (`char *nombre`) destinado a almacenar
* dinámicamente o mediante literales la identificación de la persona.
* * Un número entero (`int edad`) que represente los años de la persona.
*
* 2. Estructura de Almacenamiento (Arreglo de Estructuras):
* - En la función principal (`main`), declare un arreglo estático con
* capacidad exactamente para 3 elementos de tipo `Persona`.
* - Inicialice cada uno de los elementos del arreglo asignando valores
* válidos tanto para el puntero `nombre` como para la `edad`.
* - Implemente una función específica (cuya firma y diseño quedan a su cargo)
* que reciba como parámetro el puntero al inicio del arreglo de estructuras
* y su tamaño, y se encargue de recorrerlo sistemáticamente para
* imprimir en la consola los datos de todos sus elementos.
*
* 3. Encapsulamiento y Modificación (Funciones Modificadoras / Setters):
* - Escriba una función modular de tipo `void` llamada `cambiar_edad`
* cuya firma obligatoria sea:
* `void cambiar_edad(Persona *p, int nueva_edad)`
* - Dicha función debe recibir un puntero a una estructura `Persona`
* para actualizar el campo correspondiente de forma segura mediante
* el operador de indirección adecuado, reflejando el cambio en el ámbito
* del programa principal.
*
* 4. Pautas de Entrega y Validación:
* - El programa debe compilar sin errores ni advertencias bajo un estándar
* moderno de C (por ejemplo, -std=c11 o superior).
* - No se deben utilizar variables globales; toda la comunicación entre
* funciones debe realizarse mediante parámetros y punteros.
*******************************************************************************/
#include <stdio.h>
#define P_LENGTH 3
typedef struct{
char* nombre;
int edad;
}Persona;
void listar_personas(Persona*, int length);
void cambiar_edad(Persona *p, int nueva_edad);
int main(void){
Persona personas[P_LENGTH] = {
{
.nombre = "Horacio",
.edad = 43
},
{
.nombre = "Raquel",
.edad = 44
}, {
.nombre = "Luna",
.edad = 15
}
};
listar_personas(personas, P_LENGTH);
cambiar_edad(personas, 21);
cambiar_edad(personas+1, 22);
cambiar_edad(personas+2, -5);
listar_personas(personas, P_LENGTH);
return 0;
}
void listar_personas(Persona* p, int length){
for(int i=0; i < length; i++){
printf("%s \t %d \n", (p+i)->nombre, (p+i)->edad);
}
}
void cambiar_edad(Persona *p, int nueva_edad){
p->edad = nueva_edad;
}
BIN
View File
Binary file not shown.
+347
View File
@@ -0,0 +1,347 @@
/* =========================================================================
* PROYECTO: Sistema de Registro y Telemetría para el Nanosatélite "Andrómeda-1"
* -------------------------------------------------------------------------
* CONTEXTO:
* La Agencia Espacial Experimental está desarrollando el software de a bordo
* para su próximo nanosatélite. El sistema necesita gestionar memoria de
* forma dinámica y eficiente debido a los recursos limitados del microcontrolador
* y a la naturaleza impredecible de las ráfagas de datos en órbita.
*
* OBJETIVO:
* Diseñar e implementar un programa en lenguaje C que resuelva los siguientes
* módulos de gestión de memoria dinámica requeridos por la estación de tierra:
*
* 1. Vector Dinámico Básico (Canales de Sensores):
* Pide al operador un número N de canales activos, utiliza malloc para
* reservar un arreglo de enteros con las lecturas iniciales, muéstralo en
* consola y libera correctamente la memoria con free al terminar.
*
* 2. Cadenas Dinámicas (Identificadores de Misión):
* Escribe una función que reciba una cadena estática (char *) con el nombre
* de código del satélite, calcule su longitud exacta, reserve espacio
* dinámicamente con malloc, copie la cadena y devuelva el nuevo puntero
* dinámico para ser registrado en los logs del sistema.
*
* 3. Estructura Dinámica (Buffer de Archivos de Telemetría):
* Define una struct Archivo que contenga dos campos: size_t tamano y
* uint8_t *datos. Escribe una función que reciba el tamaño deseado y reserve
* memoria dinámicamente tanto para la estructura en sí como para su búfer
* interno de datos binarios.
*
* 4. Redimensionamiento con realloc (Stream de Datos en Tiempo Real):
* Crea una rutina que lea números enteros (paquetes de telemetría) desde
* la consola de forma indefinida hasta una condición de parada. Almacénalos
* en un arreglo dinámico que duplique su tamaño cada vez que se llene
* utilizando realloc para optimizar el almacenamiento.
*
* 5. Estructuras Anidadas Dinámicas (Subsistemas del Satélite):
* Crea una estructura principal (por ejemplo, MisionEspacial) que contenga
* un puntero a un arreglo dinámico de subestructuras (representando varios
* subsistemas como energía, propulsión y comunicación). Asegúrate de
* implementar un protocolo estricto de liberación en orden inverso
* (primero las subestructuras internas y sus recursos, luego el arreglo
* principal) para evitar fugas de memoria (memory leaks) críticas en órbita.
*
* REQUISITOS TÉCNICOS:
* - Uso obligatorio de las funciones de <stdlib.h> (malloc, realloc, free).
* - Validación de punteros (verificar que no sean NULL tras cada reserva).
* - Código limpio, modularizado en funciones y bien comentado.
* ========================================================================= */
#include <stddef.h>
#include <stdint.h>
#include <inttypes.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
typedef struct{
size_t size;
uint8_t *datos;
}TelemetryFile;
typedef struct{
TelemetryFile base;
size_t offset;
}TelemetryArray;
typedef struct{
int n_chanels;
int* chanels;
TelemetryFile* telemetry_file;
TelemetryArray telemetry_array;
}ProgramData;
void print_menu(ProgramData *);
void print_data(ProgramData *);
void get_nchanels(ProgramData *);
void get_chanels(ProgramData *);
void get_telemetry_file(ProgramData *);
TelemetryFile* telemetry_file_create(size_t fs);
void telemetry_file_free(ProgramData *);
void get_telemetry_data(ProgramData *);
bool telemetry_array_is_full(ProgramData *);
void telemetry_array_alloc(ProgramData *);
void telemetry_array_free(ProgramData *);
void telemetry_array_set(ProgramData *, uint8_t data);
void free_data(ProgramData*);
void pause(void);
int main(void){
ProgramData data = {
.n_chanels = 0,
.chanels = NULL,
.telemetry_file = NULL,
.telemetry_array = {
.base = {
.size = 0,
.datos = NULL
},
.offset = 0
}
};
print_menu(&data);
free_data(&data);
return 0;
}
void print_menu(ProgramData* ref_data){
int option = 0;
int exit = 0;
system("clear");
printf("MENU DE OPCIONES\n");
printf("\t 1- Cargar canales\n");
printf("\t 2- Mostrar Datos\n");
printf("\t 3- Crear archivo de telemetría\n");
printf("\t 4- Recibir telemetria\n");
printf("\t 5- Salir\n");
scanf("%d", &option);
switch (option) {
case 1:
get_nchanels(ref_data);
get_chanels(ref_data);
break;
case 2:
print_data(ref_data);
break;
case 3:
get_telemetry_file(ref_data);
break;
case 4:
get_telemetry_data(ref_data);
break;
case 5:
exit = 1;
break;
}
if(!exit){
print_menu(ref_data);
}
}
void get_telemetry_data(ProgramData *ref_data){
system("clear");
printf("RECEPCION DE TELEMETRIA\n");
uint8_t read_data;
do{
printf("\nIngresar valor (0 para terminar):");
scanf("%" SCNu8, &read_data);
//printf("Se ha leido: %" SCNu8 "\n", read_data);
if(read_data > 0){
telemetry_array_set(ref_data, read_data);
}
}while(read_data > 0);
}
bool telemetry_array_is_full(ProgramData *ref_data){
uint8_t* start_add = ref_data->telemetry_array.base.datos;
if(start_add == NULL){
return true;
}
uint8_t* end_add = start_add + ref_data->telemetry_array.base.size;
uint8_t* test_add = start_add + ref_data->telemetry_array.offset;
return test_add >= (end_add);
}
void telemetry_array_alloc(ProgramData *ref_data){
//Si esta vacio reserva espacio para uno.
if(ref_data->telemetry_array.base.datos == NULL){
ref_data->telemetry_array.base.datos = malloc(sizeof(uint8_t));
if(ref_data->telemetry_array.base.datos == NULL){
perror("Error asignando memoria para streaming de telemetria.");
exit(1);
}
ref_data->telemetry_array.base.size = 1;
ref_data->telemetry_array.offset = 0;
return;
}
uint8_t* result = realloc(ref_data->telemetry_array.base.datos, ref_data->telemetry_array.base.size * 2);
if(result == NULL){
perror("Error reasignando memoria para streaming de telemetria.");
exit(1);
}
ref_data->telemetry_array.base.datos = result;
ref_data->telemetry_array.base.size *= 2;
printf("La nueva capacidad es: %zu \n", ref_data->telemetry_array.base.size);
}
void telemetry_array_free(ProgramData *ref_data){
if(ref_data->telemetry_array.base.datos == NULL){
free(ref_data->telemetry_array.base.datos);
ref_data->telemetry_array.base.datos = NULL;
}
}
void telemetry_array_set(ProgramData *ref_data, uint8_t data){
if(telemetry_array_is_full(ref_data)){
printf("Esta lleno, vamos a agrandar \n");
telemetry_array_alloc(ref_data);
}
*(ref_data->telemetry_array.base.datos + ref_data->telemetry_array.offset) = data;
ref_data->telemetry_array.offset += 1;
}
void get_telemetry_file(ProgramData *ref_data){
size_t fs;
system("clear");
printf("CREAR ARCHIVO DE TELEMETRIA\n");
printf("\tEnter de size in bytes:");
scanf("%zu", &fs);
telemetry_file_free(ref_data);
ref_data->telemetry_file = telemetry_file_create(fs);
}
void telemetry_file_free(ProgramData *ref_data){
if(ref_data->telemetry_file != NULL){
if(ref_data->telemetry_file->datos != NULL){
free(ref_data->telemetry_file->datos);
ref_data->telemetry_file->datos = NULL;
}
free(ref_data->telemetry_file);
ref_data->telemetry_file = NULL;
}
}
TelemetryFile* telemetry_file_create(size_t fs){
TelemetryFile* telemetry_file = malloc(sizeof(TelemetryFile));
if(telemetry_file == NULL){
perror("Error creating telemetry file.");
exit(1);
}
telemetry_file->size = fs;
telemetry_file->datos = malloc(sizeof(uint8_t)*fs);
if(telemetry_file->datos == NULL){
free(telemetry_file);
telemetry_file = NULL;
perror("Error allocating memory for the buffer to telemetry file.");
exit(1);
}
return telemetry_file;
}
void get_nchanels(ProgramData* ref_data){
system("clear");
int n_chanels = 0;
printf("Cantidad de canales: ");
scanf("%d", &n_chanels);
ref_data->n_chanels = n_chanels;
}
void get_chanels(ProgramData* ref_data){
if(ref_data->chanels != NULL){
free(ref_data->chanels);
ref_data->chanels = NULL;
}
ref_data->chanels = malloc(sizeof(int)*ref_data->n_chanels);
if(ref_data->chanels == NULL){
perror("No se pudo reservar memoria para los canales.");
exit(1);
}
for(int i=0; i < ref_data->n_chanels; i++){
int chanel;
printf("Frecuacia en Mhz del canal%d:", i);
scanf("%d", &chanel);
*(ref_data->chanels + i) = chanel;
}
}
void print_data(ProgramData* ref_data){
system("clear");
printf("DATOS DEL PROGRAMA\n");
printf("Cantidad de canales: %d\n", ref_data->n_chanels);
for (int i=0; i < ref_data->n_chanels; i++){
printf("\t CH %d Mhz\n", *(ref_data->chanels + i));
}
if(ref_data->telemetry_file != NULL){
printf("Archivo de telemetria creado. Size: %zu bytes.\n", ref_data->telemetry_file->size);
}
printf("Datos de telemetria: ");
for(size_t i=0; i < ref_data->telemetry_array.offset; i++){
printf("%" SCNu8 ", ", *(ref_data->telemetry_array.base.datos + i));
}
if(ref_data->telemetry_array.base.size == 0){
printf("No hay datos.");
}
printf("\n");
pause();
}
void free_data(ProgramData* ref_data){
if(ref_data->chanels){
free(ref_data->chanels);
}
telemetry_file_free(ref_data);
telemetry_array_free(ref_data);
}
void pause(void){
// 1. Limpiamos el búfer por si quedó algún caracter pendiente del scanf anterior
int c;
while ((c = getchar()) != '\n' && c != EOF);
// 2. Mostramos el mensaje y esperamos a que el usuario presione Enter de verdad
printf("Presione Enter para continuar...\n");
getchar();
}
BIN
View File
Binary file not shown.
+28
View File
@@ -0,0 +1,28 @@
#include <stdio.h>
void swap(char **, char**);
void swap_int(int *, int *);
int main(void){
char *s1 = "Hola";
char *s2 = "Mundo";
int n1 = 10;
int n2 = 20;
swap(&s1, &s2);
swap_int(&n1, &n2);
printf("s1: %s s2: %s\n", s1, s2);
printf("n1: %d n2: %d\n", n1, n2);
return 0;
}
void swap(char **s1, char **s2){
char *aux = *s1;
*s1 = *s2;
*s2 = aux;
}
void swap_int(int* n1, int* n2){
int aux = *n1;
*n1 = *n2;
*n2 = aux;
}
BIN
View File
Binary file not shown.
+48
View File
@@ -0,0 +1,48 @@
/* ============================================================================
* Ejercicio: Modificación de un Puntero a través de un Puntero a Puntero (int **)
* ============================================================================
* Objetivo:
* Comprender el uso de punteros a punteros para modificar la dirección a la
* que apunta un puntero original dentro de una función (pasaje por referencia).
*
* Descripción:
* Escribe un programa en C que cumpla con los siguientes requisitos:
*
* 1. Define dos variables enteras, por ejemplo: `int x = 10;` e `int y = 20;`.
* 2. Declara un puntero simple a entero, por ejemplo: `int *ptr = &x;`.
* 3. Crea una función llamada `cambiar_puntero` que reciba un puntero a puntero
* (`int **p_ref`) y la dirección de otra variable entera (`int *nueva_dir`).
* La función debe actualizar el puntero original para que ahora apunte a
* esa nueva dirección (`*p_ref = nueva_dir;`).
* 4. En la función `main`, imprime el valor al que apunta `ptr` antes de llamar
* a la función.
* 5. Llama a `cambiar_puntero` pasando la dirección de `ptr` (`&ptr`) y la
* dirección de `y` (`&y`).
* 6. Vuelve a imprimir el valor al que apunta `ptr` después de la llamada para
* verificar que ahora apunta a `y` (su valor debe ser 20).
*
* Restricciones:
* - Debes utilizar obligatoriamente el operador de indirección doble (**).
* - No olvides validar los conceptos de memoria y desreferenciación.
* ============================================================================ */
#include <stdio.h>
void cambiar_puntero(int**, int*);
int main(void){
int x = 20, y = 30;
int* ptr = &x;
printf("contenido de ptr = %d \n", *ptr);
cambiar_puntero(&ptr, &y);
printf("contenido de ptr = %d\n", *ptr);
}
void cambiar_puntero(int** ptr, int *address){
*ptr = address;
}
BIN
View File
Binary file not shown.
BIN
View File
Binary file not shown.
BIN
View File
Binary file not shown.
BIN
View File
Binary file not shown.
BIN
View File
Binary file not shown.
BIN
View File
Binary file not shown.
BIN
View File
Binary file not shown.
BIN
View File
Binary file not shown.
BIN
View File
Binary file not shown.
BIN
View File
Binary file not shown.
BIN
View File
Binary file not shown.
BIN
View File
Binary file not shown.
BIN
View File
Binary file not shown.