Pregunta

Noté que el código C y C ++ moderno parece usar size_t en lugar de int / unsigned int prácticamente en todas partes, desde parámetros para funciones de cadena C hasta STL. Tengo curiosidad sobre la razón de esto y los beneficios que trae.

¿Fue útil?

Solución

El tipo size_t es el tipo entero sin signo que es el resultado del operador sizeof (y el operador offsetof), por lo que se garantiza que es lo suficientemente grande como para contener el tamaño del objeto más grande de su sistema puede manejar (por ejemplo, una matriz estática de 8 Gb).

El tipo unsigned int puede ser mayor, igual o menor que un <=>, y su compilador puede hacer suposiciones al respecto para la optimización.

Puede encontrar información más precisa en el estándar C99, sección 7.17, cuyo borrador está disponible en Internet en formato pdf , o en el estándar C11, sección 7.19, también disponible como borrador pdf .

Otros consejos

Classic C (el dialecto temprano de C descrito por Brian Kernighan y Dennis Ritchie en The C Programming Language, Prentice-Hall, 1978) no proporcionó size_t. El comité de estándares C presentó <=> para eliminar un problema de portabilidad

Explicado en detalle en embedded.com (con un muy buen ejemplo)

En resumen, size_t nunca es negativo, y maximiza el rendimiento porque está definido como tipo entero sin signo que es lo suficientemente grande, pero no demasiado grande, para representar el tamaño del objeto más grande posible en el plataforma de destino.

Los tamaños nunca deben ser negativos, y de hecho unsigned int es un tipo sin signo. Además, debido a que 4294967295 no tiene signo, puede almacenar números que son aproximadamente dos veces más grandes que en el tipo con signo correspondiente, porque podemos usar el bit de signo para representar la magnitud, como todos los demás bits en el entero sin signo. Cuando ganamos un bit más, estamos multiplicando el rango de números que podemos representar por un factor de aproximadamente dos.

Entonces, usted pregunta, ¿por qué no simplemente usar un unsigned long int? Es posible que no pueda contener números lo suficientemente grandes. En una implementación donde long es 32 bits, el mayor número que puede representar es unsigned long. Algunos procesadores, como el IP16L32, pueden copiar objetos de más de unsigned long long bytes.

Entonces, preguntas, ¿por qué no usar un <=>? Exige un peaje de rendimiento en algunas plataformas. El estándar C requiere que un <=> ocupe al menos 32 bits. Una plataforma IP16L32 implementa cada una de 32 bits como un par de palabras de 16 bits. Casi todos los operadores de 32 bits en estas plataformas requieren dos instrucciones, si no más, porque trabajan con los 32 bits en dos fragmentos de 16 bits. Por ejemplo, mover una longitud de 32 bits generalmente requiere dos instrucciones de la máquina: una para mover cada fragmento de 16 bits.

Usar <=> evita este costo de rendimiento. De acuerdo con este fantástico artículo , < !> quot; Tipo <=> es un typedef que es un alias para algún tipo de entero sin signo, típicamente <=> o <=>, pero posiblemente incluso <=>. Se supone que cada implementación de Standard C debe elegir el entero sin signo que sea lo suficientemente grande, pero no más grande de lo necesario, para representar el tamaño del objeto más grande posible en la plataforma de destino. & Quot;

El tipo size_t es el tipo devuelto por el operador sizeof. Es un entero sin signo capaz de expresar el tamaño en bytes de cualquier rango de memoria compatible con la máquina host. Está (típicamente) relacionado con ptrdiff_t en que ptrdiff_t es un valor entero con signo tal que sizeof (ptrdiff_t) y sizeof (size_t) son iguales.

Al escribir código C, debe siempre usar size_t siempre que se trate de rangos de memoria.

El tipo int, por otro lado, se define básicamente como el tamaño del valor entero (con signo) que la máquina host puede usar para realizar la aritmética entera de manera más eficiente. Por ejemplo, en muchas computadoras antiguas tipo PC, el valor sizeof (size_t) sería 4 (bytes) pero sizeof (int) sería 2 (byte). La aritmética de 16 bits era más rápida que la aritmética de 32 bits, aunque la CPU podía manejar un espacio de memoria (lógico) de hasta 4 GiB.

Utilice el tipo int solo cuando le interese la eficiencia, ya que su precisión real depende en gran medida de las opciones del compilador y de la arquitectura de la máquina. En particular, el estándar C especifica los siguientes invariantes: sizeof (char) & Lt; = sizeof (short) & Lt; = sizeof (int) & Lt; = sizeof (long) sin poner otras limitaciones en el representación real de la precisión disponible para el programador para cada uno de estos tipos primitivos.

Nota: Esto NO es lo mismo que en Java (que en realidad especifica la precisión de bits para cada uno de los tipos 'char', 'byte', 'short', 'int' y 'long').

Tipo size_t debe ser lo suficientemente grande como para almacenar el tamaño de cualquier objeto posible. Unsigned int no tiene que satisfacer esa condición.

Por ejemplo, en sistemas de 64 bits, int y unsigned int pueden tener 32 bits de ancho, pero size_t debe ser lo suficientemente grande como para almacenar números mayores que 4G

Este extracto del manual glibc 0.02 también puede ser relevante al investigar el tema:

Existe un problema potencial con el tipo size_t y las versiones de GCC antes del lanzamiento 2.4. ANSI C requiere que size_t siempre sea un tipo sin signo. Para compatibilidad con los archivos de encabezado de los sistemas existentes, GCC define size_t en stddef.h' to be whatever type the system's sys / types.h 'define que es. La mayoría de los sistemas Unix que definen size_t en `sys / types.h ', lo definen como un tipo con signo. Algún código en la biblioteca depende de que size_t sea un tipo sin signo, y no funcionará correctamente si está firmado.

El código de la biblioteca GNU C que espera que size_t no esté firmado es correcto. La definición de size_t como tipo con signo es incorrecta. Planeamos que en la versión 2.4, GCC siempre definirá size_t como un tipo sin signo, y el fixincludes' script will massage the system's sys / types.h 'para no entrar en conflicto con esto.

Mientras tanto, solucionamos este problema diciéndole a GCC explícitamente que use un tipo sin signo para size_t al compilar la biblioteca GNU C. `configure 'detectará automáticamente qué tipo de GCC usa para size_t organizar para anularlo si es necesario.

Si mi compilador está configurado en 32 bits, size_t no es más que un typedef para unsigned int. Si mi compilador está configurado en 64 bits, unsigned long long no es más que un typedef para <=>.

size_t es el tamaño de un puntero.

Entonces, en 32 bits o el modelo ILP32 común (entero, largo, puntero) size_t es de 32 bits. y en 64 bits o el modelo LP64 común (largo, puntero) size_t es de 64 bits (los enteros siguen siendo de 32 bits).

Hay otros modelos, pero estos son los que usa g ++ (al menos por defecto)

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top