1.8 KiB
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:
const char *version = escpos_version();
char: en esa dirección hay caracteres.*:versiones 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:
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'".