2012-08-29 26 views
10

size_t se declara como unsigned int por lo que no puede representar un valor negativo.
Entonces, ¿cuál es el ssize_t que es el tipo de size_t derecho?
Aquí es mi problema:C size_t y ssize_t valor 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; 
} 

por lo que entré:

18446744073709551591 
18446744073709551586 

como resultado?
Sé que con size_t esto podría ser posible porque es un tipo sin firmar pero ¿por qué obtuve un resultado incorrecto también con ssize_t?

+3

Está utilizando el especificador de formato incorrecto. – Mysticial

+5

'ssize_t' no está en el estándar C, proviene de POSIX. El cierre en el estándar C que viene a 'ssize_t' es' ptrdiff_t'. –

+0

'size_t' es un tipo integral sin signo, pero por lo general no es' unsigned int'. Normalmente es equivalente a 'unsigned long' o' unsigned long long'. –

Respuesta

19

En el primer caso está asignando a un tipo sin firmar - a. En el segundo caso, está utilizando el especificador de formato incorrecto. El segundo especificador debe ser %zd en lugar de %zu.

+0

@cnicutar No estoy familiarizado con los detalles de POSIX. Dado que 'printf ("% zu ", b)' espera un entero de 'sizeof (size_t)', sizeof (size_t) siempre es lo mismo que sizeof (ssize_t) para no causar daños? ¿O es 'printf ("% zu ", (size_t) b)' necesario? – chux

+0

¿Se define 'ssize_t' con el mismo tamaño que' size_t'? Si no, '"% zd "' no es una respuesta portátil. Sugerir 'printf ("% jd \ n ", (intmax_t) b);' – chux

+1

@chux '% zd' es el especificador prescrito para' ssize_t'. * La siguiente conversión entera corresponde a un argumento 'size_t' o' ssize_t'. * – cnicutar

-4

desbordamiento coz size_t es un UNSIGNED cuando se intenta establecer como size_t (val) se obtiene desbordamiento y obtener SIZE_T_MAX - val

por ejemplo: size_t val = -20; // val == 18446744073709551615 - 20;

0

Antes que nada, debe verificar el tamaño real de los dos tipos. Algo así como el siguiente fragmento debe hacer:

#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; 
} 

consigo (Linux de 64 bits, GCC v7.2) "8 bytes" en ambos casos, lo que es lo mismo, siempre y long int int y largo, la CPU máximo -nombre entero nativo

Cuando los tamaños son los mismos (y siempre deberían), size_t puede tener "2x valores absolutos más grandes" que ssize_t que, a su vez, puede tener valores firmados (que sean positivos o negativos).

Si fueran diferentes, el más grande sería ... más grande y podría acomodar valores más grandes.

Pero al final, ssize_t y size_t son dos tipos diferentes utilizados para "hablar" sobre tamaños, longitudes, cantidades de memoria, etc.

El primero solo está abandonando 1 bit por el valor para obtener el signo necesario para señalar algún tipo de error.

Finalmente, los dos tipos no son intercambiables, al menos no siempre. Cuando el tamaño puede pasar de 2^63 bytes/artículos, la diferencia es clara. size_t no se desbordará mientras que ssize_t lo hará.

En circunstancias "normales" puede transmitir de uno a otro. Para los casos que mencioné anteriormente, nunca debes mezclarlos.

Solo como referencia, strlen() y malloc() usan size_t, mientras que read() y readv() usan ssize_t.

Por lo tanto, ssize_t NO es la versión firmada de size_t ya que tienen reinos no superpuestos.

Luego, para sus preguntas, los dos números que ve difieren en 5 unidades, eso es exactamente lo que usted espera. Lo que ves es el valor de estas dos variables cuando se ve como "sin signo largo". Intente imprimirlos como "firmado largo" (% ld) en su lugar.