This commit is contained in:
2026-10-07 03:45:29 +02:00
parent 208a3e9738
commit 4351a40bd2
9 changed files with 1171 additions and 18 deletions
+64
View File
@@ -196,6 +196,70 @@ uint8_t init[] = { 0x1B, 0x40 }; /* ESC @ */
**En Go** `[2]byte{0x1B, 0x40}` es un array con su longitud dentro del tipo.
Se pasa por copia, y para pasarlo sin copiar se usa un slice: `init[:]`.
## Aritmética de punteros: `[]` también lleva un `*` escondido
Con dibujos interactivos y preguntas: [02-pointers-visual.html](02-pointers-visual.html).
Sumar un entero a un puntero da **otra dirección**: `p + i` avanza `i`
**elementos**, es decir, `i * sizeof *p` bytes. No va a la casa. Solo calcula
qué casa es.
`p[i]` es una abreviatura de `*(p + i)`: calcula la dirección y va a ella.
Igual que `->`, los corchetes llevan el `*` dentro.
La cadena completa con el buffer:
| Escribes | Equivale a | Tipo | Qué es |
|---|---|---|---|
| `buffer` | | `escpos_buffer *` | El papel (8 bytes) |
| `*buffer` | | `struct escpos_buffer` | La casa (24 bytes) |
| `buffer->data` | `(*buffer).data` | `uint8_t *` | Un papel guardado dentro de la casa, con la dirección del bloque de bytes |
| `buffer->data + i` | `&buffer->data[i]` | `uint8_t *` | La dirección de la casilla `i` |
| `buffer->data[i]` | `*(buffer->data + i)` | `uint8_t` | El byte de la casilla `i` |
Para saber si una expresión lleva `*`, cuenta: `*`, `->` y `[]` desreferencian
una vez cada uno, y `&` quita una desreferencia.
### Qué viaja cuando llamas a una función
En C, a una función le llega siempre **una copia** del valor que le pasas.
- `f(buffer)`: viaja una copia del papel, 8 bytes. La función llega a la misma
casa, así que lo que cambie en ella lo ves tú.
- `f(*buffer)`: viaja una copia de la casa, 24 bytes. Lo que cambie la función
se queda en su copia.
- `f(data)`, con `data` un array de 300 bytes: el array decae a la dirección
de su primera casilla. Viaja un papel de 8 bytes, no los 300 bytes. Dentro de
la función, `sizeof *data` es 1, el tamaño de una casilla.
### Restar direcciones
Las direcciones se escriben en hexadecimal, en base 16: cada posición vale 16
veces la de su derecha, y `a`–`f` valen 10–15.
| Hex | Decimal |
|---|---|
| `0x08` | 8 |
| `0x10` | 16 |
| `0x18` | 24 |
| `0x20` | 32 |
| `0x40` | 64 |
| `0x80` | 128 |
| `0x100` | 256 |
`0x20` es 2 × 16 + 0 = 32. Para no hacer la cuenta a mano:
- En gdb: `p 0xd210 - 0xd1f0` da `32`, y `p/x 32` da `0x20`.
- En bash: `echo $((0xd210 - 0xd1f0))`.
Si restas dos **punteros** del mismo tipo (`p &b - &a`), el resultado no son
bytes: son **elementos**, igual que en la suma. Dos `escpos_buffer *` separados
32 bytes dan `4`, porque cada uno ocupa 8.
**En Go** pasa lo mismo, todo se copia: un `*Buffer` copia el puntero y un
slice copia la cabecera (puntero, len y cap). La diferencia es que en el slice
viaja la longitud, y en C tienes que pasarla tú.
## `printf` y el formato
El primer argumento de `printf` es el **formato**. Nunca pases ahí una cadena