ssize_t - size_t c++ para que sirve
¿Qué es size_t en C? (11)
Me estoy confundiendo con size_t
en C. Sé que es devuelto por el operador sizeof
. ¿Pero qué es exactamente? ¿Es un tipo de datos?
Digamos que tengo un bucle for
:
for(i = 0; i < some_size; i++)
¿Debo usar int i;
o size_t i;
?
Como nadie lo ha mencionado aún, el significado lingüístico principal de size_t
es que el operador sizeof
devuelve un valor de ese tipo. Del mismo modo, el significado principal de ptrdiff_t
es que al restar un puntero de otro se obtendrá un valor de ese tipo. Las funciones de la biblioteca que lo aceptan lo hacen porque permitirá que dichas funciones funcionen con objetos cuyo tamaño exceda de UINT_MAX en sistemas donde puedan existir tales objetos, sin forzar a las personas que llaman a perder código que pasa un valor mayor que "unsigned int" en sistemas donde el tipo más grande Bastaría con todos los objetos posibles.
En general, si está comenzando en 0 y va hacia arriba, siempre use un tipo sin signo para evitar un desbordamiento que lo lleve a una situación de valor negativo. Esto es de vital importancia, porque si los límites de su matriz son menores que el máximo de su bucle, pero su máximo de bucle es mayor que el máximo de su tipo, se ajustará al negativo y puede experimentar una falla de segmentación (SIGSEGV ). Entonces, en general, nunca use int para un bucle que comience en 0 y vaya hacia arriba. Utilice un unsigned.
Según tengo entendido, size_t
es un entero unsigned
signo cuyo tamaño de bit es lo suficientemente grande como para contener un puntero de la arquitectura nativa.
Asi que:
sizeof(size_t) >= sizeof(void*)
size_t es un tipo de datos entero sin signo. En los sistemas que utilizan la biblioteca C de GNU, esto será sin signo int o unsigned long int. size_t se usa comúnmente para la indexación de matrices y el conteo de bucles
Según la norma ISO C de 1999 (C99),
size_t
es un tipo entero sin signo de al menos 16 bits (consulte las secciones 7.17 y 7.18.3).
size_t
es un tipo de datos sin firma definido por varios estándares C / C ++, por ejemplo, el estándar C99 ISO / IEC 9899, que se define enstddef.h
. 1 Se puede seguir importando mediante la inclusión destdlib.h
ya que este archivo incluyestddef.h
.Este tipo se utiliza para representar el tamaño de un objeto. Las funciones de biblioteca que toman o devuelven tamaños esperan que sean de tipo o que tengan el tipo de devolución de
size_t
. Además, el tamaño del operador basado en compilador más frecuentemente usado debe evaluarse a un valor constante que sea compatible consize_t
.
Como una implicación, size_t
es un tipo garantizado para mantener cualquier índice de matriz.
size_t
e int
no son intercambiables. Por ejemplo, en Linux de 64 bits, size_t
tiene un tamaño de 64 bits (es decir, sizeof(void*)
) pero int
es de 32 bits.
También tenga en cuenta que size_t
no está firmado. Si necesita una versión firmada, entonces hay ssize_t
en algunas plataformas y sería más relevante para su ejemplo.
Como regla general, sugeriría usar int
para la mayoría de los casos generales y solo usar size_t
/ ssize_t
cuando exista una necesidad específica mmap()
por ejemplo, mmap()
).
size_t
es un tipo que puede contener cualquier índice de matriz.
Dependiendo de la implementación, puede ser cualquiera de:
unsigned char
unsigned short
unsigned int
unsigned long
unsigned long long
Aquí es cómo se define size_t
en stddef.h
de mi máquina:
typedef unsigned long size_t;
size_t
es un tipo sin signo. Por lo tanto, no puede representar ningún valor negativo (<0). Lo usa cuando está contando algo y está seguro de que no puede ser negativo. Por ejemplo, strlen()
devuelve un size_t
porque la longitud de una cadena debe ser al menos 0.
En su ejemplo, si su índice de bucle siempre va a ser mayor que 0, podría tener sentido usar size_t
, o cualquier otro tipo de datos sin firmar.
Cuando utiliza un objeto size_t
, debe asegurarse de que en todos los contextos que se utiliza, incluida la aritmética, desea valores no negativos. Por ejemplo, digamos que tienes:
size_t s1 = strlen(str1);
size_t s2 = strlen(str2);
y quieres encontrar la diferencia de las longitudes de str2
y str1
. Tú no puedes hacer:
int diff = s2 - s1; /* bad */
Esto se debe a que el valor asignado a diff
siempre será un número positivo, incluso cuando s2 < s1
, porque el cálculo se realiza con tipos sin signo. En este caso, dependiendo de cuál sea su caso de uso, es mejor que use int
(o long long
) para s1
y s2
.
Hay algunas funciones en C / POSIX que podrían / deberían usar size_t
, pero no por razones históricas. Por ejemplo, el segundo parámetro para fgets
idealmente debería ser size_t
, pero es int
.
Si eres del tipo empírico ,
echo | gcc -E -xc -include ''stddef.h'' - | grep size_t
Salida para Ubuntu 14.04 64-bit GCC 4.8:
typedef long unsigned int size_t;
Tenga en cuenta que stddef.h
es proporcionado por GCC y no glibc bajo src/gcc/ginclude/stddef.h
en GCC 4.2.
Interesantes apariciones en C99.
malloc
tomasize_t
como argumento, por lo que determina el tamaño máximo que se puede asignar.Y como también se devuelve por
sizeof
, creo que limita el tamaño máximo de cualquier matriz.Ver también: ¿Cuál es el tamaño máximo de una matriz en C?
size_t o cualquier tipo sin signo se puede ver como una variable de bucle, ya que las variables de bucle suelen ser mayores o iguales a 0.
Cuando usamos un objeto size_t , tenemos que asegurarnos de que en todos los contextos que se usa, incluida la aritmética, solo queremos valores no negativos. Por ejemplo, el siguiente programa definitivamente daría el resultado inesperado:
// C program to demonstrate that size_t or
// any unsigned int type should be used
// carefully when used in a loop
#include<stdio.h>
int main()
{
const size_t N = 10;
int a[N];
// This is fine
for (size_t n = 0; n < N; ++n)
a[n] = n;
// But reverse cycles are tricky for unsigned
// types as can lead to infinite loop
for (size_t n = N-1; n >= 0; --n)
printf("%d ", a[n]);
}
Output
Infinite loop and then segmentation fault