Veo variables definidas con este tipo pero no sé de dónde viene, ni cuál es su propósito. ¿Por qué no usar int o unsigned int? (¿Qué pasa con otros tipos "similares"? Void_t, etc.).
Veo variables definidas con este tipo pero no sé de dónde viene, ni cuál es su propósito. ¿Por qué no usar int o unsigned int? (¿Qué pasa con otros tipos "similares"? Void_t, etc.).
Respuestas:
De Wikipedia
Los archivos de encabezado
stdlib.h
ystddef.h
definen un tipo de datos llamadosize_t
1 que se usa para representar el tamaño de un objeto. Las funciones de biblioteca que toman tamaños esperan que sean de tiposize_t
, y el operador sizeof se evalúa comosize_t
.El tipo real de
size_t
depende de la plataforma; un error común es asumir quesize_t
es lo mismo que unsigned int, lo que puede conducir a errores de programación, 2 particularmente a medida que las arquitecturas de 64 bits se vuelven más frecuentes.
Desde C99 7.17.1 / 2
Los siguientes tipos y macros se definen en el encabezado estándar
stddef.h
<snip>
size_t
que es el tipo entero sin signo del resultado del operador sizeof
int
y unsigned int
son de 32 bits, mientras que size_t es de 64 bits.
De acuerdo con la descripción de size_t en en.cppreference.com size_t
se define en los siguientes encabezados:
std::size_t
...
Defined in header <cstddef>
Defined in header <cstdio>
Defined in header <cstring>
Defined in header <ctime>
Defined in header <cwchar>
size_t
es el tipo entero sin signo del resultado del operador sizeof (ISO C99 Sección 7.17.)
El sizeof
operador da el tamaño (en bytes) de su operando, que puede ser una expresión o el nombre entre paréntesis de un tipo. El tamaño se determina a partir del tipo de operando. El resultado es un número entero. El valor del resultado se define por la implementación y su tipo (un tipo entero sin signo) es size_t
(ISO C99 Sección 6.5.3.4.)
En términos prácticos, size_t
representa la cantidad de bytes que puede abordar. En la mayoría de las arquitecturas modernas durante los últimos 10-15 años, ha sido de 32 bits, que también ha sido del tamaño de un int sin firmar. Sin embargo, nos estamos moviendo a un direccionamiento de 64 bits, mientras que uint
lo más probable es que se mantenga en 32 bits (su tamaño no está garantizado en el estándar c ++). Para hacer que su código que depende del tamaño de la memoria sea portátil entre arquitecturas, debe usar un size_t
. Por ejemplo, cosas como los tamaños de matriz siempre deben usar size_t
's. Si observa los contenedores estándar, ::size()
siempre devuelve un size_t
.
También tenga en cuenta que Visual Studio tiene una opción de compilación que puede verificar este tipo de errores denominada "Detectar problemas de portabilidad de 64 bits".
De esta manera siempre sabrá cuál es el tamaño, porque un tipo específico está dedicado a los tamaños. La propia pregunta muestra que puede ser un problema: ¿es una int
o una unsigned int
? Además, ¿cuál es la magnitud ( short
, int
, long
, etc.)?
Debido a que hay un tipo específico asignado, no tiene que preocuparse por la longitud o el signo.
La definición real se puede encontrar en la biblioteca de referencia de C ++ , que dice:
Tipo:
size_t
(tipo integral sin firmar)Encabezamiento:
<cstring>
size_t
corresponde al tipo de datos integral devuelto por el operador de lenguajesizeof
y se define en el<cstring>
archivo de encabezado (entre otros) como un tipo integral sin firmar.En
<cstring>
, se utiliza como el tipo del parámetronum
en las funcionesmemchr
,memcmp
,memcpy
,memmove
,memset
,strncat
,strncmp
,strncpy
ystrxfrm
, que en todos los casos que se utiliza para especificar el número máximo de bytes o caracteres la función tiene que afectar.También se utiliza como el tipo de cambio de
strcspn
,strlen
,strspn
ystrxfrm
para tamaños de retorno y longitudes.
size_t debe definirse en los encabezados de su biblioteca estándar. En mi experiencia, generalmente es simplemente un typedef para unsigned int. Sin embargo, el punto es que no tiene por qué ser así. Los tipos como size_t permiten al proveedor de bibliotecas estándar la libertad de cambiar sus tipos de datos subyacentes si es apropiado para la plataforma. Si asume que size_t siempre es unsigned int (mediante conversión, etc.), podría tener problemas en el futuro si su proveedor cambia size_t para que sea, por ejemplo, un tipo de 64 bits. Es peligroso asumir algo sobre esta o cualquier otro tipo de biblioteca por este motivo.
No estoy familiarizado void_t
excepto como resultado de una búsqueda en Google (se usa en una vmalloc
biblioteca por Kiem-Phong Vo en AT&T Research ; estoy seguro de que también se usa en otras bibliotecas).
Las diversas definiciones de tipo xxx_t se utilizan para abstraer un tipo de una implementación definida particular, ya que los tipos concretos utilizados para ciertas cosas pueden diferir de una plataforma a otra. Por ejemplo:
Void_t
abstrae el tipo de puntero devuelto por las vmalloc
rutinas de la biblioteca porque fue escrito para funcionar en sistemas anteriores a ANSI / ISO C donde elvoid
palabra clave podría no existir. Al menos eso es lo que supongo.wchar_t
abstrae el tipo utilizado para caracteres anchos ya que en algunos sistemas será de 16 bits, en otros será de 32 bits.Entonces, si escribe su código de manejo de caracteres amplios para usar el wchar_t
tipo en lugar de, digamos unsigned short
, ese código probablemente será más portátil para varias plataformas.
En programas minimalistas donde una size_t
definición no se cargó "por casualidad" en algunos include pero todavía la necesito en algún contexto (por ejemplo, para acceder std::vector<double>
), entonces uso ese contexto para extraer el tipo correcto. Por ejemplo typedef std::vector<double>::size_type size_t
.
(Rodee con namespace {...}
si es necesario para limitar el alcance).
En cuanto a "¿Por qué no usar int o unsigned int?", Simplemente porque semánticamente es más significativo no hacerlo. Existe la razón práctica por la que puede ser, digamos, typedef
d como an int
y luego actualizarse a un long
posterior, sin que nadie tenga que cambiar su código, por supuesto, pero más fundamentalmente que se supone que un tipo es significativo. Para simplificar enormemente, una variable de tipo size_t
es adecuada y se usa para contener los tamaños de las cosas, al igual que lo time_t
es para contener valores de tiempo. La forma en que estos se implementan realmente debería ser una tarea de implementación bastante adecuada. En comparación con simplemente llamar a todo int
, el uso de nombres de tipo significativos como este ayuda a aclarar el significado y la intención de su programa, al igual que lo hace cualquier conjunto rico de tipos.