# Punteros y cadenas ## En C no hay tipo `string` En Go, `string` es un tipo propio: por dentro guarda un puntero y una longitud, y lo manejas como un valor. En C, una cadena es solo una secuencia de bytes en memoria terminada en `'\0'`. La longitud **no se guarda en ningún sitio**: para saberla hay que recorrer la cadena hasta encontrar el `'\0'`. ``` "1.0.0" → '1' '.' '0' '.' '0' '\0' (6 bytes, no 5) ``` Los literales como `"1.0.0"` viven en **memoria de solo lectura**. Si intentas escribir en ellos, el comportamiento es indefinido; en la práctica, el programa se cierra. ## `const char *` Una función que "devuelve una cadena" en realidad devuelve **la dirección de su primer byte**: ```c const char *version = escpos_version(); ``` - `char`: en esa dirección hay caracteres. - `*`: `version` es un puntero; guarda una dirección, no un carácter. - `const`: a través de este puntero no se pueden modificar los caracteres. `char` es un **entero de 1 byte**. Si guardas un puntero en un `char`, pierdes la dirección. Por eso el error dice `makes pointer from integer`. ## Los dos significados de `*` | Dónde aparece | Qué significa | |---|---| | En una **declaración**: `const char *p` | "`p` es un puntero" | | En una **expresión**: `*p` | "el valor que hay en la dirección de `p`" (desreferenciar) | Si `p` apunta a `"1.0.0"`, `*p` es solo el `'1'`. **En Go**: es lo mismo que `var p *T` frente a `*p`. ## `printf` y el formato El primer argumento de `printf` es el **formato**. Nunca pases ahí una cadena variable: ```c printf(s); /* mal */ printf("%s\n", s); /* bien */ ``` Si `s` contuviera un `%`, `printf` iría a leer argumentos que no existen, lo que es comportamiento indefinido y un agujero de seguridad clásico (*format string*). `%s` significa "imprime los bytes desde esta dirección hasta el `'\0'`".