PDA

Visualizza la versione completa : [c]itoa


cristianc
10-05-2008, 14:12
Ho un'altro problema con le funzioni di libreria.
nel solito programma ho usato la funzione itoa per convertire da interi in stringa:

itoa(pInt[k], strNum, 10);
Compilando ricevo i seguenti errori:

menu.c:(.text+0x4e1): undefined reference to `itoa' menu.c:(.text+0x5bc): undefined reference to `itoa'
Come faccio a sapere dov'e' il bug e a rimuoverlo?

shodan
10-05-2008, 14:20
Se non ricordo male, itoa non è una funzione della libreria standard. Alcuni compilatori la implementano, altri no. Al suo posto meglio usare sprintf.

Esempio.



char dest[16];
sprintf(dest,"%i",10);

cristianc
10-05-2008, 14:35
ho qualche dubbio nell'uso di sprintf nell'uso degli argomenti.
Io devo prendere un valore intero,in questo caso pInt[k] e metterlo in una stringa,in questo caso strNum.
dest va bene cosi come 10.Ma non ho capito cosa fa %i.

MItaly
10-05-2008, 14:37
Meglio la snprintf, così da prevenire potenziali buffer overrun.


#include <stdio.h>
#define ARRSIZE(arr) ((size_t)(sizeof(arr)/sizeof(*arr)))
/* ... */
char dest[16];
snprintf(dest,ARRSIZE(dest),"%i",10);

shodan
10-05-2008, 14:41
Originariamente inviato da cristianc
Ma non ho capito cosa fa %i.

La sprintf e la versione più sicura e consigliata snprintf, prendono gli stessi formattatori della printf. Ti rimando alla documentazione di printf per sapere quali sono e cosa fanno.

cristianc
10-05-2008, 14:51
Ho letto un po la documentazione e mi dice questo:
'd', 'i' : stampa un intero come decimale con segno. '%d' e '%i' sono sinonimi per l'output, ma diversi se usati con scanf() per l'input;
Pero' ancora non ho capito come faccio a mettere un intero in una stringa.

MItaly
10-05-2008, 15:19
Così:

Originariamente inviato da MItaly


#include <stdio.h>
#define ARRSIZE(arr) ((size_t)(sizeof(arr)/sizeof(*arr)))
/* ... */
char dest[16];
snprintf(dest,ARRSIZE(dest),"%i",10);

cristianc
10-05-2008, 15:34
nella documentazione e' un po diversa.

Come alternativa, molti ambienti forniscono la funzione snprintf: int snprintf(char *str, size_t size, const char *format, ...) snprintf garantisce di non scrivere più di size bytes in str, in modo da evitare il rischio di un buffer overflow, come nel codice seguente: #define BUFFER_SIZE 50 char buf[BUFFER_SIZE]; int n; ... n = snprintf(buf, BUFFER_SIZE, "Your name is %s.\n", username); if (n < 0 || n >= BUFFER_SIZE) /* Handle error */

Volevo sapere poi dov'era nell'argomento il numero da inserire nella stringa.
L'identificatore %i serve a dire che il dato in input e' intero ,vero?
Non ho compreso il pericolo dell'overflow a meno che non si metta un limite.

oregon
10-05-2008, 15:59
Originariamente inviato da cristianc
nella documentazione e' un po diversa.

E in cosa sarebbe diversa da come l'ha usata MItaly ? Controlla bene ...

MItaly
10-05-2008, 16:07
Originariamente inviato da cristianc
nella documentazione e' un po diversa.

Fidati che la snprintf si usa così...

Volevo sapere poi dov'era nell'argomento il numero da inserire nella stringa.
L'identificatore %i serve a dire che il dato in input e' intero ,vero?
No, serve a dire che l'argomento che segue va considerato come un intero con segno.

Non ho compreso il pericolo dell'overflow a meno che non si metta un limite.
Se tu scrivi


char dest[8];
sprintf(dest,"%i",123456789);

incorri in un buffer overflow, dal momento che sprintf sforerà gli 8 caratteri allocati per dest. Usando la snprintf invece sei sicuro di non sforare il buffer; i numeri che superano la lunghezza del buffer saranno troncati, ma avrai evitato il pericolo di buffer overflow (che apre falle di sicurezza e conduce quasi sempre al crash del programma).
Potresti obiettare che usando un buffer sufficientemente grande puoi evitare completamente il problema (12 caratteri sono sufficienti per qualunque intero a 32 bit con segno), ma ti conviene comunque usare snprintf, perché qualora portassi il tuo programma ad una piattaforma a 64 bit dove gli int sono interi a 64 bit la lunghezza del buffer non sarebbe più sufficiente (servirebbero 22 caratteri), e durante un porting è facile dimenticarsi di cambiare le dimensioni dei buffer.
Insomma, impiegare snprintf invece di sprintf non costa nulla e dà un margine di sicurezza in più, quindi perché non usarlo?

Loading