En varios ejemplos de C ++ veo un uso del tipo size_tdonde habría usado un simple int. ¿Cuál es la diferencia y por qué size_tdebería ser mejor?
En varios ejemplos de C ++ veo un uso del tipo size_tdonde habría usado un simple int. ¿Cuál es la diferencia y por qué size_tdebería ser mejor?
Respuestas:
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.
Además, verifique por qué size_t importa
/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.
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.
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.
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".
La definición de SIZE_Tse encuentra en:
https://msdn.microsoft.com/en-us/library/cc441980.aspx y https://msdn.microsoft.com/en-us/library/cc230394.aspx
Pegando aquí la información requerida:
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.
Este tipo se declara de la siguiente manera:
typedef unsigned __int3264 ULONG_PTR;
SIZE_Tno es lo size_tque preguntó el OP.
SIZE_Tes totalmente diferente de size_t. No puede declarar una variable de tipo SIZE_T.