comparando off_t y ssize_t con otros tipos

Soy nuevo en C y recientemente tuve problemas con los tipos de datos no coincidentes y su asignación de memoria. Estoy escribiendo un progtwig muy simple para calcular la sum de comprobación xor de un archivo leído mediante llamadas al sistema Linux.

Mi pregunta es la siguiente: ¿Debo preocuparme por resultados impredecibles al comparar off_t o ssize_t con long o int ?

Por ejemplo:

long i; for(i = 0; i < fileStat.st_size; i++) { // do stuff } 

y también:

 ssize_t i; for(i = 0; i < fileStat.st_size; i++) { // do stuff } 

La comparación de tipos de la misma firmeza pero de diferente tamaño con el otro funciona, ya que el tipo más pequeño se extiende al tipo más grande. La comparación de tipos de firmas diferentes es problemática, ya que podría obtener resultados incorrectos si el tipo firmado no es más grande que el tipo sin signo y el número firmado es negativo. Es una buena idea asegurarse de que el número firmado no sea negativo al principio:

 signed_t a; unsigned_t b; /* instead of */ if (a < b) /* ... */ /* use */ if (a < 0 || a < b) /* ... */ 

El estándar C indica que el tipo long es lo suficientemente grande como para representar la constante LONG_MAX , que debe ser al menos 2147483647 (2 31 -1). Si tomamos este límite inferior como el valor de LONG_MAX , entonces es posible que no sea lo suficientemente grande. Es uno menos de 2 GiB, después de todo.

ssize_t no está en el estándar C, pero está definido en el estándar POSIX. Debe ser lo suficientemente grande como para representar la constante SSIZE_MAX , que debe ser al menos 32767 (2 15 -1). No confíes en este tipo tampoco.

En mi máquina, long y ssize_t tienen 4 bytes. Puede verificar los tamaños usted mismo utilizando el operador sizeof . Puede obtener diferentes resultados. Si desea que su progtwig sea portátil, no confíe en algo específico de la implementación.

Por último, si realmente no quieres usar esos typedefs, te recomiendo usar el tipo unsigned long long . Es lo suficientemente grande como para representar la constante ULLONG_MAX , que debe ser al menos 18446744073709551615 (2 64 -1).

Véase también: http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/limits.h.html

Las advertencias sobre la comparación entre enteros con signo y sin signo (y otras operaciones aritméticas) se derivan de las conversiones implícitas que se producen cuando dos operandos de tipo diferente se combinan con un operador.

Hay un buen capítulo sobre este tema en el manual que acompaña a la herramienta PC-Lint de Gimpel.

Una lectura de los documentos de estándares C disponibles en particular “promociones enteras” es útil.

por ejemplo, en http://www.open-std.org/jtc1/sc22/WG14/www/docs/n1256.pdf (C99) – sección 6.3.1 “Operandos aritméticos”

En particular, “si un int puede representar todos los valores del tipo original, el valor se convierte en un int; de lo contrario, se convierte en un int sin signo”

Por lo tanto, en ese contexto, “-1” se convertirá a todos binarios binarios [dependientes de la implementación] como un número sin signo, lo que podría dar resultados sorprendentes a los incautos. por ejemplo, una cantidad de entero sin signo dividida por el entero “-1” dará cero.

La respuesta allí es convertir el unsigned en un valor firmado antes de la aritmética.

Tenga en cuenta que sizeof () devuelve un valor sin signo.