Si esas son sus únicas opciones, use intif some_sizeestá firmado, size_tsi no está firmado.
Nate
8
@Nate Eso es incorrecto. POSIX tiene un tipo ssize_t pero el tipo realmente correcto para usar es ptrdiff_t.
Steven Stewart-Gallus
2
Las respuestas no son tan claras como en la Programación de bajo nivel: C, ensamblaje y ejecución de programas en Intel® 64 . Como se indica en el libro, el uso de un índice int ipuede no ser suficiente para abordar una gran variedad. Entonces, al usar size_t ipuede abordar más índices, por lo que incluso si tiene una gran matriz que no debería ser un problema. size_tes un tipo de datos: generalmente un unsigned long intpero esto depende de su sistema.
De acuerdo con el estándar ISO C 1999 (C99), size_tes un tipo entero sin signo de al menos 16 bits (ver secciones 7.17 y 7.18.3).
size_tes un tipo de datos sin signo definido por varios estándares C / C ++, por ejemplo, el estándar C99 ISO / IEC 9899, que se define en stddef.h. 1 Puede importarse aún más mediante la inclusión de
stdlib.heste archivo como subincluye internamente stddef.h.
Este tipo se usa para representar el tamaño de un objeto. Las funciones de biblioteca que toman o devuelven tamaños esperan que sean de tipo o tengan el tipo de retorno de size_t. Además, el tamaño de operador basado en compilador más frecuentemente utilizado debe evaluarse a un valor constante que sea compatible con
size_t.
Como consecuencia, size_tes un tipo garantizado para contener cualquier índice de matriz.
"Las funciones de biblioteca que toman o devuelven tamaños esperan que sean del tipo ... size_t" Excepto que stat () usa off_t para el tamaño de un archivo
Draemon
64
@Draemon Ese comentario refleja una confusión fundamental. size_tes para objetos en la memoria. El estándar C ni siquiera define stat()o off_t(esas son definiciones POSIX) ni nada que ver con discos o sistemas de archivos; se detiene en las FILEtransmisiones. La gestión de la memoria virtual es completamente diferente de los sistemas de archivos y la gestión de archivos en lo que respecta a los requisitos de tamaño, por lo que mencionar off_taquí es irrelevante.
jw013
3
@ jw013: difícilmente lo llamaría una confusión fundamental, pero usted hace un punto interesante. Aún así, el texto citado no dice "tamaños de objetos en memoria", y "desplazamiento" no es un buen nombre para un tipo de tamaño, independientemente de dónde esté almacenado.
Draemon
30
@Draemon Buen punto. Esta respuesta cita Wikipedia, que en este caso no tiene la mejor explicación, en mi opinión. El estándar C en sí mismo es mucho más claro: se define size_tcomo el tipo de resultado del sizeofoperador (7.17p2 aproximadamente <stddef.h>). La sección 6.5 explica exactamente cómo funcionan las expresiones C (6.5.3.4 para sizeof). Como no puede aplicar sizeofa un archivo de disco (principalmente porque C ni siquiera define cómo funcionan los discos y los archivos), no hay lugar para la confusión. En otras palabras, culpe a Wikipedia (y esta respuesta por citar Wikipedia y no el estándar C real).
jw013
2
@Draemon: también estaría de acuerdo con la evaluación de "confusión fundamental". Si no ha leído los estándares C / C ++, podría pensar que "objeto" se refiere a "programación orientada a objetos", lo cual no es así. Lea el estándar C, que no tiene ninguno de esos objetos OOP, pero aún tiene objetos, y descúbralo. ¡La respuesta puede sorprenderte!
Heath Hunnicutt
220
size_tEs un tipo sin signo. Por lo tanto, no puede representar ningún valor negativo (<0). Lo usa cuando cuenta algo y está seguro de que no puede ser negativo. Por ejemplo, strlen()devuelve un size_tporque la longitud de una cadena debe ser al menos 0.
En su ejemplo, si su índice de bucle será siempre mayor que 0, podría tener sentido usar size_t, o cualquier otro tipo de datos sin signo.
Cuando usas un size_t objeto, debe asegurarse de que en todos los contextos que se usa, incluida la aritmética, desee valores no negativos. Por ejemplo, supongamos que tiene:
y quieres encontrar la diferencia de las longitudes de str2ystr1 . Tú no puedes hacer:
int diff = s2 - s1;/* bad */
Esto se debe a que el valor asignado diffsiempre 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 s1y 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 fgetsideal debería ser size_t, pero es int.
@Alok: Dos preguntas: 1) ¿de qué tamaño es size_t? 2) ¿por qué debería preferir size_talgo como unsigned int?
Lazer
2
@Lazer: el tamaño de size_tes sizeof(size_t). El estándar C garantiza que SIZE_MAXserá al menos 65535. size_tes el tipo devuelto por el sizeofoperador y se utiliza en la biblioteca estándar (por ejemplo, strlendevoluciones size_t). Como dijo Brendan, size_tno tiene por qué ser lo mismo que unsigned int.
Alok Singhal
44
@Lazer: sí, size_tse garantiza que es un tipo sin firmar.
Alok Singhal
2
@ Celeritas no, quiero decir que un tipo sin signo solo puede representar valores no negativos. Probablemente debería haber dicho "No puede representar valores negativos".
Alok Singhal
44
@JasonOster, el complemento a dos no es un requisito en el estándar C. Si el valor de s2 - s1desborda un int, el comportamiento es indefinido.
Alok Singhal
73
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
Así size_tes como se define en stddef.hmi máquina:
Ciertamente typedef unsigned long size_tdepende del compilador. ¿O estás sugiriendo que siempre es así?
chux - Restablece a Monica el
44
@chux: De hecho, solo porque una implementación lo defina como tal no significa que todos lo hagan. Caso en cuestión: Windows de 64 bits. unsigned longes de 32 bits, size_tes de 64 bits.
Tim Čas
2
¿Cuál es el propósito de size_t exactamente? Cuando puedo crear una variable para mí como: "int mysize_t;" o "long mysize_t" o "unsigned long mysize_t". ¿Por qué alguien debería haber creado esta variable para mí?
midkin
1
@midkin size_tno es una variable. Es un tipo que puede usar cuando desea representar el tamaño de un objeto en la memoria.
Arjun Sreedharan
1
¿Es cierto que size_tsiempre hay 32 bits en una máquina de 32 bits, 64 bits también?
Tengo el mismo entorno, sin embargo, lo probé durante 32 bits, pasando la opción "-m32" de GCC, el resultado fue: "typedef unsigned int size_t". Gracias por compartir este increíble comando @Ciro, ¡me ayudó mucho! :-)
silvioprog
2
El asunto en sí no es confuso. Es la mente confusa que intenta hacer muchas preguntas y dar muchas respuestas. Me sorprende que esta respuesta y la de Arjun Sreedharan todavía no impidan que la gente pregunte y responda.
biocyberman
1
Gran respuesta, porque en realidad te dice qué size_tes , al menos en una distribución popular de Linux.
Como nadie lo ha mencionado aún, el significado lingüístico principal de size_tes que el sizeofoperador devuelve un valor de ese tipo. Del mismo modo, el significado principal de ptrdiff_tes que restar un puntero de otro producirá un valor de ese tipo. Las funciones de biblioteca que lo aceptan lo hacen porque permitirá que tales funciones funcionen con objetos cuyo tamaño exceda UINT_MAX en sistemas donde tales objetos podrían existir, sin obligar a las personas que llaman a desperdiciar código que pasa un valor mayor que "unsigned int" en sistemas donde el tipo más grande bastaría para todos los objetos posibles.
Mi pregunta siempre ha sido: si sizeof nunca existió, ¿habría necesidad de size_t?
Dean P
@DeanP: Quizás no, aunque entonces habría una pregunta sobre qué tipo de argumento debería usarse para cosas como malloc(). En lo personal, me hubiera gustado tener versiones visto que toman argumentos de tipo int, longy long long, con algunas implementaciones que promueven tipos más cortos y otros de aplicación, por ejemplo lmalloc(long n) {return (n < 0 || n > 32767) ? 0 : imalloc(n);}[en algunas plataformas, llamando a imalloc(123)sería más barato que llamar lmalloc(123);, e incluso en una plataforma en la que size_tes 16 bits, código que desea asignar el tamaño calculado en un valor `largo` ...
supercat
... debería poder confiar en que la asignación falla si el valor es mayor de lo que el asignador puede manejar.
supercat
11
Para entrar en por qué size_tnecesitaba existir y cómo llegamos aquí:
En términos pragmáticos, size_ty ptrdiff_tse garantiza que tienen 64 bits de ancho en una implementación de 64 bits, 32 bits de ancho en una implementación de 32 bits, y así sucesivamente. No podían obligar a ningún tipo existente a querer decir eso, en cada compilador, sin romper el código heredado.
A size_to ptrdiff_tno es necesariamente lo mismo que un intptr_to uintptr_t. Eran diferentes en ciertas arquitecturas que todavía estaban en uso cuando size_ty ptrdiff_tse agregaron a la norma en los últimos años 80, y se conviertan en obsoletos cuando C99 añadió muchos nuevos tipos pero no han ido todavía (como Windows de 16 bits). El x86 en modo protegido de 16 bits tenía una memoria segmentada donde la matriz o estructura más grande posible podía tener solo 65.536 bytes de tamaño, pero un farpuntero debía tener 32 bits de ancho, más ancho que los registros. En esos, intptr_thabría sido de 32 bits de ancho pero size_typtrdiff_tpodría tener 16 bits de ancho y caber en un registro. ¿Y quién sabía qué tipo de sistema operativo podría escribirse en el futuro? En teoría, la arquitectura i386 ofrece un modelo de segmentación de 32 bits con punteros de 48 bits que ningún sistema operativo ha utilizado realmente.
El tipo de compensación de memoria no podría deberse a longque demasiado código heredado supone que longtiene exactamente 32 bits de ancho. Esta suposición incluso se incorporó a las API de UNIX y Windows. Desafortunadamente, muchos otros códigos heredados también asumieron que a longes lo suficientemente ancho como para contener un puntero, un desplazamiento de archivo, la cantidad de segundos que han transcurrido desde 1970, y así sucesivamente. POSIX ahora proporciona una forma estandarizada de forzar que la última suposición sea verdadera en lugar de la primera, pero tampoco es una suposición portátil.
No podría ser intporque solo un pequeño puñado de compiladores en los años 90 tenía int64 bits de ancho. Luego se volvieron realmente raros al mantener long32 bits de ancho. La próxima revisión del Estándar declaró ilegal intque sea más ancho long, pero intaún tiene 32 bits de ancho en la mayoría de los sistemas de 64 bits.
No podría ser long long int, lo que de todos modos se agregó más tarde, ya que se creó para tener al menos 64 bits de ancho incluso en sistemas de 32 bits.
Entonces, se necesitaba un nuevo tipo. Incluso si no fuera así, todos esos otros tipos significaban algo más que un desplazamiento dentro de una matriz u objeto. Y si hubo una lección del fiasco de la migración de 32 a 64 bits, fue ser específico acerca de qué propiedades debía tener un tipo, y no usar uno que significara cosas diferentes en diferentes programas.
No está de acuerdo con " size_ty ptrdiff_tse garantiza que tendrá 64 bits de ancho en una implementación de 64 bits", etc. La garantía es exagerada. El rango de size_tes impulsado principalmente por la capacidad de memoria de la implementación. "una implementación de n bits" es principalmente el ancho del procesador nativo de enteros. Ciertamente, muchas implementaciones usan una memoria de tamaño similar y un ancho de bus de procesador, pero existen enteros anchos con memoria escasa o procesadores estrechos con mucha memoria y separan estas dos propiedades de implementación.
chux - Restablece a Mónica el
8
size_ty intno son intercambiables Por ejemplo, en Linux de size_t64 bits tiene un tamaño de 64 bits (es decir sizeof(void*)) pero intes de 32 bits.
También tenga en cuenta que size_tno está firmado. Si necesita una versión firmada, la hay ssize_ten algunas plataformas y sería más relevante para su ejemplo.
Como regla general, sugeriría usar intpara la mayoría de los casos generales y solo usar size_t/ ssize_tcuando exista una necesidad específica ( mmap()por ejemplo).
En general, si está comenzando en 0 y va hacia arriba, use siempre un tipo sin signo para evitar un desbordamiento que lo lleve a una situación de valor negativo. Esto es críticamente importante, porque si los límites de su matriz son menores que el máximo de su bucle, pero su max de bucle es mayor que el máximo de su tipo, se ajustará a negativo y puede experimentar una falla de segmentación (SIGSEGV ) Entonces, en general, nunca use int para un ciclo que comienza en 0 y va hacia arriba. Use un sin firmar.
No puedo aceptar tu argumentación. ¿Dice que es mejor que el error de desbordamiento silenciosamente conduzca a acceder a datos válidos dentro de su matriz?
maf-soft
1
@ maf-soft es correcto. Si el error no se detecta, es peor que un bloqueo del programa. ¿Por qué esta respuesta recibió votos positivos?
yoyo_fun
Si accede a datos válidos en su matriz, entonces no es un error porque el tipo sin signo no se desbordará en el límite con el tipo con signo. ¿Qué es esta lógica chicos? Digamos por alguna razón que usas char para iterar sobre una matriz de 256 elementos ... firmado se desbordará en 127 y el elemento 128 sigsegv, pero si usas unsigned, pasará por toda la matriz como se esperaba. Por otra parte, cuando está utilizando un int, sus matrices no serán realmente más grandes que 2 mil millones de elementos, por lo que de cualquier manera, no importa ...
Purple Ice
1
No puedo imaginar ninguna situación en la que el desbordamiento de enteros no sea un error, ya sea que sea positivo o negativo. ¡El hecho de que no obtenga un segfault no significa que vea un comportamiento correcto! Y puede experimentar una falla de segmentación, o no, si su desplazamiento es positivo o negativo; Todo depende de su diseño de memoria. @PurpleIce, no creo que estés diciendo lo mismo que esta respuesta; Su argumento parece ser que debe elegir un tipo de datos lo suficientemente grande como para contener el valor más grande que desea poner en él, lo cual es simplemente sentido común.
Soren Bjornstad
Dicho esto, prefiero usar un tipo sin signo para los índices de bucle semánticamente ; si su variable nunca va a ser negativa, entonces también podría indicarlo en el tipo que elija. También podría permitir que el compilador detecte un error donde el valor terminó siendo negativo, aunque GCC al menos es bastante terrible al detectar este error en particular (en una ocasión inicialicé un sin signo a -1 y no recibí una advertencia). Del mismo modo, un size_t es semánticamente apropiado para los índices de matriz.
Soren Bjornstad
3
size_t es un tipo de datos entero sin signo. En los sistemas que usan la Biblioteca GNU C, esto será unsigned int o unsigned long int. size_t se usa comúnmente para la indexación de matrices y el conteo de bucles.
size_t o cualquier tipo sin signo puede verse usado como variable de bucle ya que las variables de bucle son típicamente mayores o iguales a 0.
Cuando usamos un objeto size_t , debemos 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(){constsize_t N =10;int a[N];// This is finefor(size_t n =0; n < N;++n)
a[n]= n;// But reverse cycles are tricky for unsigned // types as can lead to infinite loopfor(size_t n = N-1; n >=0;--n)
printf("%d ", a[n]);}OutputInfinite loop and then segmentation fault
size_tes un tipo de datos entero sin signo que puede asignar solo valores enteros 0 y mayores que 0. Mide los bytes del tamaño de cualquier objeto y los devuelve el sizeofoperador.
constes la representación de sintaxis size_t, pero sin constusted puede ejecutar el programa.
constsize_t number;
size_tSe utiliza regularmente para la indexación de matrices y el conteo de bucles. Si el compilador 32-bitfunciona, funcionaría unsigned int. Si el compilador es 64-bitfuncionaría unsigned long long inttambién. Hay para el tamaño máximo de size_tdependiendo del tipo de compilador.
size_tya definir el <stdio.h>archivo de cabecera, pero también puede definir por
<stddef.h>, <stdlib.h>, <string.h>, <time.h>, <wchar.h>cabeceras.
Ejemplo (con const)
#include<stdio.h>int main(){constsize_t value =200;size_t i;int arr[value];for(i =0; i < value ;++i){
arr[i]= i;}size_t size =sizeof(arr);
printf("size = %zu\n", size);}
Salida -:size = 800
Ejemplo (sin const)
#include<stdio.h>int main(){size_t value =200;size_t i;int arr[value];for(i =0; i < value ;++i){
arr[i]= i;}size_t size =sizeof(arr);
printf("size = %zu\n", size);}
Según tengo entendido, size_tes un unsignednúmero entero cuyo tamaño de bits es lo suficientemente grande como para contener un puntero de la arquitectura nativa.
No es verdad. El tamaño del puntero puede ser mayor que el size_t. Varios ejemplos: los compiladores de C en modo real x86 pueden tener 32 bits FARo HUGEpunteros, pero size_t sigue siendo de 16 bits. Otro ejemplo: Watcom C solía tener un puntero gordo especial para memoria extendida que tenía 48 bits de ancho, pero size_tno lo era. En el controlador embebido con arquitectura Harvard, tampoco tiene correlación, porque ambos se refieren a diferentes espacios de direcciones.
int
ifsome_size
está firmado,size_t
si no está firmado.int i
puede no ser suficiente para abordar una gran variedad. Entonces, al usarsize_t i
puede abordar más índices, por lo que incluso si tiene una gran matriz que no debería ser un problema.size_t
es un tipo de datos: generalmente ununsigned long int
pero esto depende de su sistema.Respuestas:
De Wikipedia :
Como consecuencia,
size_t
es un tipo garantizado para contener cualquier índice de matriz.fuente
size_t
es para objetos en la memoria. El estándar C ni siquiera definestat()
ooff_t
(esas son definiciones POSIX) ni nada que ver con discos o sistemas de archivos; se detiene en lasFILE
transmisiones. La gestión de la memoria virtual es completamente diferente de los sistemas de archivos y la gestión de archivos en lo que respecta a los requisitos de tamaño, por lo que mencionaroff_t
aquí es irrelevante.size_t
como el tipo de resultado delsizeof
operador (7.17p2 aproximadamente<stddef.h>
). La sección 6.5 explica exactamente cómo funcionan las expresiones C (6.5.3.4 parasizeof
). Como no puede aplicarsizeof
a un archivo de disco (principalmente porque C ni siquiera define cómo funcionan los discos y los archivos), no hay lugar para la confusión. En otras palabras, culpe a Wikipedia (y esta respuesta por citar Wikipedia y no el estándar C real).size_t
Es un tipo sin signo. Por lo tanto, no puede representar ningún valor negativo (<0). Lo usa cuando cuenta algo y está seguro de que no puede ser negativo. Por ejemplo,strlen()
devuelve unsize_t
porque la longitud de una cadena debe ser al menos 0.En su ejemplo, si su índice de bucle será siempre mayor que 0, podría tener sentido usar
size_t
, o cualquier otro tipo de datos sin signo.Cuando usas un
size_t
objeto, debe asegurarse de que en todos los contextos que se usa, incluida la aritmética, desee valores no negativos. Por ejemplo, supongamos que tiene:y quieres encontrar la diferencia de las longitudes de
str2
ystr1
. Tú no puedes hacer:Esto se debe a que el valor asignado
diff
siempre será un número positivo, incluso cuandos2 < 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 useint
(olong long
) paras1
ys2
.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ámetrofgets
ideal debería sersize_t
, pero esint
.fuente
size_t
? 2) ¿por qué debería preferirsize_t
algo comounsigned int
?size_t
essizeof(size_t)
. El estándar C garantiza queSIZE_MAX
será al menos 65535.size_t
es el tipo devuelto por elsizeof
operador y se utiliza en la biblioteca estándar (por ejemplo,strlen
devolucionessize_t
). Como dijo Brendan,size_t
no tiene por qué ser lo mismo queunsigned int
.size_t
se garantiza que es un tipo sin firmar.s2 - s1
desborda unint
, el comportamiento es indefinido.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
Así
size_t
es como se define enstddef.h
mi máquina:fuente
typedef unsigned long size_t
depende del compilador. ¿O estás sugiriendo que siempre es así?unsigned long
es de 32 bits,size_t
es de 64 bits.size_t
no es una variable. Es un tipo que puede usar cuando desea representar el tamaño de un objeto en la memoria.size_t
siempre hay 32 bits en una máquina de 32 bits, 64 bits también?Si eres del tipo empírico ,
Salida para Ubuntu 14.04 64-bit GCC 4.8:
Tenga en cuenta que
stddef.h
es proporcionado por GCC y no glibcsrc/gcc/ginclude/stddef.h
en GCC 4.2.Apariciones interesantes en C99
malloc
tomasize_t
como argumento, por lo que determina el tamaño máximo que se puede asignar.Y dado que también es devuelto 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?
fuente
size_t
es , al menos en una distribución popular de Linux.La página de manual para types.h dice:
fuente
Como nadie lo ha mencionado aún, el significado lingüístico principal de
size_t
es que elsizeof
operador devuelve un valor de ese tipo. Del mismo modo, el significado principal deptrdiff_t
es que restar un puntero de otro producirá un valor de ese tipo. Las funciones de biblioteca que lo aceptan lo hacen porque permitirá que tales funciones funcionen con objetos cuyo tamaño exceda UINT_MAX en sistemas donde tales objetos podrían existir, sin obligar a las personas que llaman a desperdiciar código que pasa un valor mayor que "unsigned int" en sistemas donde el tipo más grande bastaría para todos los objetos posibles.fuente
malloc()
. En lo personal, me hubiera gustado tener versiones visto que toman argumentos de tipoint
,long
ylong long
, con algunas implementaciones que promueven tipos más cortos y otros de aplicación, por ejemplolmalloc(long n) {return (n < 0 || n > 32767) ? 0 : imalloc(n);}
[en algunas plataformas, llamando aimalloc(123)
sería más barato que llamarlmalloc(123);
, e incluso en una plataforma en la quesize_t
es 16 bits, código que desea asignar el tamaño calculado en un valor `largo` ...Para entrar en por qué
size_t
necesitaba existir y cómo llegamos aquí:En términos pragmáticos,
size_t
yptrdiff_t
se garantiza que tienen 64 bits de ancho en una implementación de 64 bits, 32 bits de ancho en una implementación de 32 bits, y así sucesivamente. No podían obligar a ningún tipo existente a querer decir eso, en cada compilador, sin romper el código heredado.A
size_t
optrdiff_t
no es necesariamente lo mismo que unintptr_t
ouintptr_t
. Eran diferentes en ciertas arquitecturas que todavía estaban en uso cuandosize_t
yptrdiff_t
se agregaron a la norma en los últimos años 80, y se conviertan en obsoletos cuando C99 añadió muchos nuevos tipos pero no han ido todavía (como Windows de 16 bits). El x86 en modo protegido de 16 bits tenía una memoria segmentada donde la matriz o estructura más grande posible podía tener solo 65.536 bytes de tamaño, pero unfar
puntero debía tener 32 bits de ancho, más ancho que los registros. En esos,intptr_t
habría sido de 32 bits de ancho perosize_t
yptrdiff_t
podría tener 16 bits de ancho y caber en un registro. ¿Y quién sabía qué tipo de sistema operativo podría escribirse en el futuro? En teoría, la arquitectura i386 ofrece un modelo de segmentación de 32 bits con punteros de 48 bits que ningún sistema operativo ha utilizado realmente.El tipo de compensación de memoria no podría deberse a
long
que demasiado código heredado supone quelong
tiene exactamente 32 bits de ancho. Esta suposición incluso se incorporó a las API de UNIX y Windows. Desafortunadamente, muchos otros códigos heredados también asumieron que along
es lo suficientemente ancho como para contener un puntero, un desplazamiento de archivo, la cantidad de segundos que han transcurrido desde 1970, y así sucesivamente. POSIX ahora proporciona una forma estandarizada de forzar que la última suposición sea verdadera en lugar de la primera, pero tampoco es una suposición portátil.No podría ser
int
porque solo un pequeño puñado de compiladores en los años 90 teníaint
64 bits de ancho. Luego se volvieron realmente raros al mantenerlong
32 bits de ancho. La próxima revisión del Estándar declaró ilegalint
que sea más ancholong
, peroint
aún tiene 32 bits de ancho en la mayoría de los sistemas de 64 bits.No podría ser
long long int
, lo que de todos modos se agregó más tarde, ya que se creó para tener al menos 64 bits de ancho incluso en sistemas de 32 bits.Entonces, se necesitaba un nuevo tipo. Incluso si no fuera así, todos esos otros tipos significaban algo más que un desplazamiento dentro de una matriz u objeto. Y si hubo una lección del fiasco de la migración de 32 a 64 bits, fue ser específico acerca de qué propiedades debía tener un tipo, y no usar uno que significara cosas diferentes en diferentes programas.
fuente
size_t
yptrdiff_t
se garantiza que tendrá 64 bits de ancho en una implementación de 64 bits", etc. La garantía es exagerada. El rango desize_t
es impulsado principalmente por la capacidad de memoria de la implementación. "una implementación de n bits" es principalmente el ancho del procesador nativo de enteros. Ciertamente, muchas implementaciones usan una memoria de tamaño similar y un ancho de bus de procesador, pero existen enteros anchos con memoria escasa o procesadores estrechos con mucha memoria y separan estas dos propiedades de implementación.size_t
yint
no son intercambiables Por ejemplo, en Linux desize_t
64 bits tiene un tamaño de 64 bits (es decirsizeof(void*)
) peroint
es de 32 bits.También tenga en cuenta que
size_t
no está firmado. Si necesita una versión firmada, la hayssize_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 usarsize_t
/ssize_t
cuando exista una necesidad específica (mmap()
por ejemplo).fuente
En general, si está comenzando en 0 y va hacia arriba, use siempre un tipo sin signo para evitar un desbordamiento que lo lleve a una situación de valor negativo. Esto es críticamente importante, porque si los límites de su matriz son menores que el máximo de su bucle, pero su max de bucle es mayor que el máximo de su tipo, se ajustará a negativo y puede experimentar una falla de segmentación (SIGSEGV ) Entonces, en general, nunca use int para un ciclo que comienza en 0 y va hacia arriba. Use un sin firmar.
fuente
size_t es un tipo de datos entero sin signo. En los sistemas que usan la Biblioteca GNU C, esto será unsigned int o unsigned long int. size_t se usa comúnmente para la indexación de matrices y el conteo de bucles.
fuente
size_t o cualquier tipo sin signo puede verse usado como variable de bucle ya que las variables de bucle son típicamente mayores o iguales a 0.
Cuando usamos un objeto size_t , debemos 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:
fuente
size_t
es un tipo de datos entero sin signo que puede asignar solo valores enteros 0 y mayores que 0. Mide los bytes del tamaño de cualquier objeto y los devuelve elsizeof
operador.const
es la representación de sintaxissize_t
, pero sinconst
usted puede ejecutar el programa.size_t
Se utiliza regularmente para la indexación de matrices y el conteo de bucles. Si el compilador32-bit
funciona, funcionaríaunsigned int
. Si el compilador es64-bit
funcionaríaunsigned long long int
también. Hay para el tamaño máximo desize_t
dependiendo del tipo de compilador.size_t
ya definir el<stdio.h>
archivo de cabecera, pero también puede definir por<stddef.h>
,<stdlib.h>
,<string.h>
,<time.h>
,<wchar.h>
cabeceras.const
)Salida -:
size = 800
const
)Salida -:
size = 800
fuente
Según tengo entendido,
size_t
es ununsigned
número entero cuyo tamaño de bits es lo suficientemente grande como para contener un puntero de la arquitectura nativa.Entonces:
fuente
size_t
. Varios ejemplos: los compiladores de C en modo real x86 pueden tener 32 bitsFAR
oHUGE
punteros, pero size_t sigue siendo de 16 bits. Otro ejemplo: Watcom C solía tener un puntero gordo especial para memoria extendida que tenía 48 bits de ancho, perosize_t
no lo era. En el controlador embebido con arquitectura Harvard, tampoco tiene correlación, porque ambos se refieren a diferentes espacios de direcciones.size_t