2012-08-29 12 views
10

size_t è dichiarato come unsigned int in modo che non possa rappresentare un valore negativo.
Quindi c'è ssize_t che è il firmato tipo di size_t giusto?
Ecco il mio problema:C size_t e ssize_t valore negativo

#include <stdio.h> 
#include <sys/types.h> 

int main(){ 
size_t a = -25; 
ssize_t b = -30; 
printf("%zu\n%zu\n", a, b); 
return 0; 
} 

perché ho ottenuto:

18446744073709551591 
18446744073709551586 

come risultato?
So che con size_t questo potrebbe essere possibile perché è un tipo senza segno, ma perché ho ottenuto un risultato errato anche con ssize_t ??

+3

Si sta utilizzando l'identificatore di formato errato. – Mysticial

+5

'ssize_t' non è in C standard, viene da POSIX. La chiusura in C standard che arriva a 'ssize_t' è' ptrdiff_t'. –

+0

'size_t' è un tipo integrale senza segno, ma di solito non è' unsigned int'. Tipicamente equivale a "unsigned long" o "unsigned long long". –

risposta

19

Nel primo caso si sta assegnando un tipo senza segno - a. Nel secondo caso utilizzi l'identificatore di formato sbagliato. Il secondo identificatore deve essere %zd anziché %zu.

+0

@cnicutar Non ha familiarità con i dettagli POSIX. Dato che 'printf ("% zu ", b)' si aspetta un intero di 'sizeof (size_t)', sizeof (size_t) è sempre uguale a sizeof (ssize_t) per non causare danno? O è necessario 'printf ("% zu ", (size_t) b)? – chux

+0

Si dice che 'ssize_t' abbia la stessa dimensione di' size_t'? Altrimenti, '"% zd "' non è una risposta portatile. Suggerisci 'printf ("% jd \ n ", (intmax_t) b);' – chux

+1

@chux '% zd' è lo specificatore prescritto per' ssize_t'. * Una successiva conversione di numeri interi corrisponde a un argomento 'size_t' o' ssize_t'. * – cnicutar

-4

Overflow coz size_t è un UNSIGNED quando si tenta di impostare size_t come (Val) si ottiene troppo pieno e ottenere SIZE_T_MAX - val

ad esempio: size_t val = -20; // val == 18446744073709551615 - 20;

0

Prima di tutto è necessario verificare la dimensione effettiva dei due tipi. Qualcosa come il seguente frammento dovrebbe fare:

#include <stdio.h> 
#include <unistd.h> 

int main() { 
    printf("sizeof( size_t) = %d bytes\n",(int) sizeof(size_t)); 
    printf("sizeof(ssize_t) = %d bytes\n",(int) sizeof(ssize_t)); 
    return 0; 
} 

ottengo (64bit Linux, GCC v7.2) "8 byte" in entrambi i casi, il che è lo stesso di long long int int e lunga, il massimo della CPU -nero valore intero.

Quando le dimensioni sono uguali (e dovrebbero sempre essere), size_t può avere "2x valori assoluti più grandi" di ssize_t che, a sua volta, può avere valori firmati (vale a dire positivi o negativi).

Se fossero diversi, il più grande sarebbe ... più grande e potrebbe quindi contenere valori maggiori.

Ma alla fine, ssize_t e size_t sono due diversi tipi utilizzati per "parlare" di dimensioni, lunghezze, quantità di memoria e così via.

Il primo si limita ad abbandonare 1 bit per il valore per ottenere il segno necessario per segnalare una sorta di errore.

Infine, i due tipi non sono intercambiabili, non sempre almeno. Quando la dimensione può andare oltre 2^63 byte/elementi la differenza è chiara. size_t non avrà overflow mentre ssize_t lo farà.

In circostanze "normali" è possibile trasmettere da uno all'altro. Per i casi che ho menzionato prima, non dovresti mai mescolarli.

Proprio come riferimento, sia strlen() che malloc() utilizzano size_t, mentre sia read() che readv() usano ssize_t.

Quindi, ssize_t NON è la versione firmata di size_t poiché hanno regni non sovrapposti.

Quindi, per le tue domande, i due numeri che vedi differiscono di 5 unità, questo è esattamente ciò che ti aspetti. Quello che vedi è il valore di thsoe due variabili viste come "unsigned long". Prova invece a stamparli come "firmati long" (% ld).