Los archivos de encabezado stdlib.h y stddef.h definen un tipo de datos llamado size_t que se usa para representar el tamaño de un objeto. Las funciones de biblioteca que toman tamaños esperan que sean del tipo size_t, y el operador sizeof se evalúa como size_t.
El tipo real de size_t depende de la plataforma; Un error común es asumir que size_t es lo mismo que unsigned int, lo que puede conducir a errores de programación, particularmente a medida que las arquitecturas de 64 bits se vuelven más frecuentes.
@NDEthos ¡Depende! En este caso, Linux /usr/include/stdlib.hobtiene la definición /usr/lib/gcc/x86_64-redhat-linux/5.3.1/include/stddef.hy en ella está predeterminada a long unsigned intmenos que algún otro archivo de encabezado indique lo contrario.
David Tonhofer
1
Confirmo que size_t para int tuncation es peligroso . Esto podría estar fuera de tema, pero ¿cómo escribir un parche solo para corregir ese tipo de errores cuando ocurre miles de veces en el kernel de Linux?
user2284570
36
size_t es el tipo utilizado para representar tamaños (como su nombre lo indica). Su plataforma (e incluso su implementación potencial) depende y solo debe usarse para este propósito. Obviamente, representando un tamaño, size_t no está firmado. Muchas funciones stdlib, incluidas malloc, sizeof y varias funciones de operación de cadena, usan size_t como tipo de datos.
Un int está firmado de manera predeterminada, y aunque su tamaño también depende de la plataforma, será un fijo de 32 bits en la mayoría de las máquinas modernas (y aunque size_t es de 64 bits en la arquitectura de 64 bits, int tiene 32 bits de largo en esas arquitecturas).
Para resumir: use size_t para representar el tamaño de un objeto e int (o long) en otros casos.
El size_ttipo se define como el tipo integral sin signo del sizeofoperador. En el mundo real, a menudo verá intdefinido como 32 bits (para compatibilidad con versiones anteriores) pero size_tdefinido como 64 bits (para que pueda declarar matrices y estructuras de más de 4 GiB de tamaño) en plataformas de 64 bits. Si a long inttambién es de 64 bits, esto se llama la convención LP64; si long intes de 32 bits long long inty los punteros son de 64 bits, eso es LLP64. También puede obtener el reverso, un programa que utiliza instrucciones de velocidad de 64 bits, pero punteros de 32 bits para ahorrar memoria. Además, intestá firmado y size_tno está firmado.
Históricamente hubo una serie de otras plataformas donde las direcciones eran más anchas o más cortas que el tamaño nativo de int. De hecho, en los años 70 y principios de los 80, esto era más común que no: todos los microordenadores populares de 8 bits tenían registros de 8 bits y direcciones de 16 bits, y la transición entre 16 y 32 bits también produjo muchas máquinas que tenía direcciones más anchas que sus registros. Ocasionalmente todavía veo preguntas aquí sobre Borland Turbo C para MS-DOS, cuyo modo de memoria enorme tenía direcciones de 20 bits almacenadas en 32 bits en una CPU de 16 bits (pero que podría admitir el conjunto de instrucciones de 32 bits del 80386); el Motorola 68000 tenía una ALU de 16 bits con registros y direcciones de 32 bits; hubo mainframes de IBM con direcciones de 15 bits, 24 bits o 31 bits. También puede ver diferentes tamaños de ALU y bus de dirección en sistemas integrados.
Cualquier momento intes menor size_te intenta almacenar el tamaño o el desplazamiento de un archivo u objeto muy grande en un archivo unsigned int, existe la posibilidad de que se desborde y cause un error. Con un int, también existe la posibilidad de obtener un número negativo. Si an into unsigned intes más ancho, el programa se ejecutará correctamente pero desperdiciará memoria.
En general, debe usar el tipo correcto para el propósito si desea portabilidad. Mucha gente recomendará que use matemáticas firmadas en lugar de sin firmar (para evitar errores desagradables y sutiles 1U < -3). A tal fin, los define la biblioteca estándar ptrdiff_ten <stddef.h>que el tipo de firmado el resultado de restar un puntero de otro.
Dicho esto, una solución alternativa podría ser verificar los límites de todas las direcciones y compensaciones INT_MAXy, 0o INT_MINsegún corresponda, y activar las advertencias del compilador sobre la comparación de cantidades firmadas y no firmadas en caso de que pierda alguna. Siempre, siempre, siempre debe verificar el desbordamiento de sus accesos de matriz en C de todos modos.
Creo que size_t en realidad está garantizado como un alias para un entero sin signo, por lo que no puede ser una estructura. Sin embargo, no tengo una referencia útil para respaldar esto en este momento.
relajarse
9
@unwind: C99: TC3, 7.17 §2
Christoph
1
@danio ¿Por qué es así? ¿Puedes explicarlo?
Buitre de Rüppell
2
¡No me vincularía a cplusplus si fuera tú! Si no puede citar capítulos, versos, párrafos y líneas, ¡todo es solo un rumor! :-)
graham.reeds
1
size_tse especifica como un tipo entero sin signo . C11 §6.5.3.4 5 "El valor del resultado de ambos operadores ( sizeof_Alignof) está definido por la implementación, y su tipo (un tipo entero sin signo) es size_t".
SIZE_Tes una ULONG_PTRrepresentación del número máximo de bytes a los que puede apuntar un puntero.
Este tipo se declara de la siguiente manera:
typedef ULONG_PTR SIZE_T;
A ULONG_PTRes un tipo largo sin signo utilizado para la precisión del puntero. Se utiliza cuando se convierte un puntero en un tipo largo para realizar la aritmética del puntero.
Respuestas:
De la amigable Wikipedia :
Además, verifique por qué size_t importa
fuente
/usr/include/stdlib.h
obtiene la definición/usr/lib/gcc/x86_64-redhat-linux/5.3.1/include/stddef.h
y en ella está predeterminada along unsigned int
menos que algún otro archivo de encabezado indique lo contrario.size_t es el tipo utilizado para representar tamaños (como su nombre lo indica). Su plataforma (e incluso su implementación potencial) depende y solo debe usarse para este propósito. Obviamente, representando un tamaño, size_t no está firmado. Muchas funciones stdlib, incluidas malloc, sizeof y varias funciones de operación de cadena, usan size_t como tipo de datos.
Un int está firmado de manera predeterminada, y aunque su tamaño también depende de la plataforma, será un fijo de 32 bits en la mayoría de las máquinas modernas (y aunque size_t es de 64 bits en la arquitectura de 64 bits, int tiene 32 bits de largo en esas arquitecturas).
Para resumir: use size_t para representar el tamaño de un objeto e int (o long) en otros casos.
fuente
El
size_t
tipo se define como el tipo integral sin signo delsizeof
operador. En el mundo real, a menudo veráint
definido como 32 bits (para compatibilidad con versiones anteriores) perosize_t
definido como 64 bits (para que pueda declarar matrices y estructuras de más de 4 GiB de tamaño) en plataformas de 64 bits. Si along int
también es de 64 bits, esto se llama la convención LP64; silong int
es de 32 bitslong long int
y los punteros son de 64 bits, eso es LLP64. También puede obtener el reverso, un programa que utiliza instrucciones de velocidad de 64 bits, pero punteros de 32 bits para ahorrar memoria. Además,int
está firmado ysize_t
no está firmado.Históricamente hubo una serie de otras plataformas donde las direcciones eran más anchas o más cortas que el tamaño nativo de
int
. De hecho, en los años 70 y principios de los 80, esto era más común que no: todos los microordenadores populares de 8 bits tenían registros de 8 bits y direcciones de 16 bits, y la transición entre 16 y 32 bits también produjo muchas máquinas que tenía direcciones más anchas que sus registros. Ocasionalmente todavía veo preguntas aquí sobre Borland Turbo C para MS-DOS, cuyo modo de memoria enorme tenía direcciones de 20 bits almacenadas en 32 bits en una CPU de 16 bits (pero que podría admitir el conjunto de instrucciones de 32 bits del 80386); el Motorola 68000 tenía una ALU de 16 bits con registros y direcciones de 32 bits; hubo mainframes de IBM con direcciones de 15 bits, 24 bits o 31 bits. También puede ver diferentes tamaños de ALU y bus de dirección en sistemas integrados.Cualquier momento
int
es menorsize_t
e intenta almacenar el tamaño o el desplazamiento de un archivo u objeto muy grande en un archivounsigned int
, existe la posibilidad de que se desborde y cause un error. Con unint
, también existe la posibilidad de obtener un número negativo. Si anint
ounsigned int
es más ancho, el programa se ejecutará correctamente pero desperdiciará memoria.En general, debe usar el tipo correcto para el propósito si desea portabilidad. Mucha gente recomendará que use matemáticas firmadas en lugar de sin firmar (para evitar errores desagradables y sutiles
1U < -3
). A tal fin, los define la biblioteca estándarptrdiff_t
en<stddef.h>
que el tipo de firmado el resultado de restar un puntero de otro.Dicho esto, una solución alternativa podría ser verificar los límites de todas las direcciones y compensaciones
INT_MAX
y,0
oINT_MIN
según corresponda, y activar las advertencias del compilador sobre la comparación de cantidades firmadas y no firmadas en caso de que pierda alguna. Siempre, siempre, siempre debe verificar el desbordamiento de sus accesos de matriz en C de todos modos.fuente
Es porque size_t puede ser cualquier cosa que no sea un int (tal vez una estructura). La idea es que desacople su trabajo del tipo subyacente.
fuente
size_t
se especifica como un tipo entero sin signo . C11 §6.5.3.4 5 "El valor del resultado de ambos operadores (sizeof
_Alignof
) está definido por la implementación, y su tipo (un tipo entero sin signo) essize_t
".La definición de
SIZE_T
se encuentra en: https://msdn.microsoft.com/en-us/library/cc441980.aspx y https://msdn.microsoft.com/en-us/library/cc230394.aspxPegando aquí la información requerida:
SIZE_T
es unaULONG_PTR
representación del número máximo de bytes a los que puede apuntar un puntero.Este tipo se declara de la siguiente manera:
A
ULONG_PTR
es un tipo largo sin signo utilizado para la precisión del puntero. Se utiliza cuando se convierte un puntero en un tipo largo para realizar la aritmética del puntero.Este tipo se declara de la siguiente manera:
fuente
SIZE_T
no es losize_t
que preguntó el OP.SIZE_T
es totalmente diferente desize_t
. No puede declarar una variable de tipoSIZE_T
.