¿Está definido el valor máximo de size_t (SIZE_MAX) en relación con los otros tipos de enteros?
Estoy escribiendo una biblioteca de funciones que convertirán de forma segura entre varios tipos numéricos o intentarán morir. Mi intención es más o menos igual que crear-útil-biblioteca y aprender-C-edge-cases.
Miint
-a-size_t
la función está activando un CCG-Wtype-limits
advirtiendo que afirma que no debería probar si unint
es mayor queSIZE_MAX
, porque nunca será cierto. (Otra función que convierteint
assize_t
produce una advertencia idéntica sobreSSIZE_MAX
.)
Mi MCVE, con comentarios adicionales y pequeños pasos, es:
#include <stdint.h> /* SIZE_MAX */
#include <stdlib.h> /* exit EXIT_FAILURE size_t */
extern size_t i2st(int value) {
if (value < 0) {
exit(EXIT_FAILURE);
}
// Safe to cast --- not too small.
unsigned int const u_value = (unsigned int) value;
if (u_value > SIZE_MAX) { /* Line 10 */
exit(EXIT_FAILURE);
}
// Safe to cast --- not too big.
return (size_t) u_value;
}
Las advertencias del compiladorRecibo advertencias similares de GCC 4.4.5 en Linux 2.6.34:
$ gcc -std=c99 -pedantic -Wall -Wextra -c -o math_utils.o math_utils.c
math_utils.c: In function ‘i2st’:
math_utils.c:10: warning: comparison is always false due to limited range of data type
... y también de GCC 4.8.5 en Linux 3.10.0:
math_utils.c: In function ‘i2st’:
math_utils.c:10:5: warning: comparison is always false due to limited range of data type [-Wtype-limits]
if (u_value > SIZE_MAX) { /* Line 10 */
^
Estas advertencias no me parecen justificadas, al menos no en el caso general. (No niego que la comparación pueda ser "siempre falsa" en alguna combinación particular de hardware y compilador).
El estándar CLa norma C 1999 no parece descartar unint
ser mayor queSIZE_MAX
.
Sección "6.5.3.4 Elsizeof
operador "no abordasize_t
en absoluto, excepto para describirlo como "definido en<stddef.h>
(y otros encabezados) ".
Sección "7.17 Definiciones comunes<stddef.h>
"definesize_t
como "el tipo entero sin signo del resultado de lasizeof
operador ". (¡Gracias chicos!)
La sección "7.18.3 Límites de otros tipos enteros" es más útil --- define "límite desize_t
" como:
SIZE_MAX
65535
...sentidoSIZE_MAX
podría ser tanpequeña como 65535. Unint
(firmado o sin firmar) podría ser mucho mayor que eso, dependiendo del hardware y el compilador.
La respuesta aceptada a "unsigned int
vs.size_t
"parece apoyar mi interpretación (énfasis agregado):
lossize_t
tipo puede ser mayor que, igual a,o más pequeño que ununsigned int
, y su compilador puede hacer suposiciones al respecto para la optimización.
Esta respuesta cita la misma "Sección 7.17" del estándar C que ya he citado.
Otros documentosMis búsquedas aparecieron en el documento de Open Group "Neutralidad del tamaño de datos y soporte de 64 bits", que afirma bajo" Modelos de datos de 64 bits "(énfasis agregado):
ISO / IEC 9899: 1990, Lenguajes de programación - C (ISO C) dejó la definición deshort int
, elint
, ellong int
, y elpointer
deliberadamente vago [...] Las únicas limitaciones eran queint
s no debe ser menor queshort
s, ylong
s no debe ser menor queint
s, ysize_t
debe representar el tipo sin signo más grande compatible con una implementación. [...] La relación entre los tipos de datos fundamentales se puede expresar como:
sizeof(char)
<=sizeof(short)
<=sizeof(int)
<=sizeof(long)
= sizeof(size_t)
Si esto es cierto, entonces prueba unint
en contraSIZE_MAX
de hecho es inútil ... pero este artículo no cita capítulos y versos, por lo que no puedo decir cómo sus autores llegaron a su conclusión. Su propia "Versión de especificación básica 7"sys/types.h
docs no aborde esto de ninguna manera.
Entiendo quesize_t
es poco probable que sea más angosto que unint
, pero¿La garantía estándar C esa comparaciónsome_unsigned_int > SIZE_MAX
serásiempre ser falso? ¿Si es así, donde?
Hay dos semi-duplicados de esta pregunta, pero ambos hacen preguntas más generales sobre quésize_t
se supone que representa y cuándo debería / no debería usarse.
"Que essize_t
¿Cía?"no aborda la relación entresize_t
y los otros tipos enteros. Su respuesta aceptada es solo una cita de Wikipedia, que no proporciona ninguna información más allá de lo que ya he encontrado.
"¿Cuál es la definición correcta desize_t
?"comienza casi un duplicado de mi pregunta, pero luego se desvía, preguntando cuándosize_t
debe usarse y por qué se introdujo. Se cerró como un duplicado de la pregunta anterior.