Buscar..


Char puede estar sin firmar o firmado

El estándar no especifica si char debe estar firmado o sin firmar. Diferentes compiladores lo implementan de manera diferente, o podrían permitir cambiarlo usando un interruptor de línea de comando.

Tamaño de los tipos integrales.

Los siguientes tipos se definen como tipos integrales :

  • char
  • Tipos enteros firmados
  • Tipos de enteros sin signo
  • char16_t y char32_t
  • bool
  • wchar_t

Con la excepción de sizeof(char) / sizeof(signed char) / sizeof(unsigned char) , que se divide entre § 3.9.1.1 [basic.fundamental / 1] y § 5.3.3.1 [expr.sizeof], y sizeof(bool) , que está completamente definido por la implementación y no tiene un tamaño mínimo, los requisitos de tamaño mínimo de estos tipos se indican en la sección § 3.9.1 [basic.fundamental] de la norma, y ​​se detallarán a continuación.

Tamaño de char

Todas las versiones de estándar el C ++ especifican, en § 5.3.3.1, que sizeof rendimientos 1 para unsigned char , signed char , y char (es definido por la implementación si el char tipo se signed o unsigned ).

C ++ 14

char es lo suficientemente grande como para representar 256 valores diferentes, para ser adecuado para almacenar unidades de código UTF-8.

Tamaño de los tipos enteros con signo y sin signo

El estándar especifica, en el § 3.9.1.2, que en la lista de tipos enteros con signo estándar , que constan de caracteres con signed char , short int , int , long int long long int , cada tipo proporcionará al menos tanto almacenamiento como los anteriores en la lista. Además, como se especifica en el § 3.9.1.3, cada uno de estos tipos tiene un tipo de entero sin signo estándar correspondiente, unsigned char unsigned short int unsigned int , unsigned short int unsigned int , unsigned int unsigned long int , unsigned long int unsigned long long int , que tiene el mismo tamaño y alineación que Su correspondiente tipo firmado. Además, como se especifica en el § 3.9.1.1, char tiene los mismos requisitos de tamaño y alineación que el signed char y el unsigned char .

C ++ 11

Antes de C ++ 11, long long y unsigned long long no formaban parte oficialmente del estándar C ++. Sin embargo, después de su introducción a C, en C99, muchos compiladores admitieron long long como un tipo entero con signo extendido , y unsigned long long como un tipo entero sin signo extendido , con las mismas reglas que los tipos C.

La norma garantiza así que:

1 == sizeof(char)  == sizeof(signed char) == sizeof(unsigned char)
  <= sizeof(short) == sizeof(unsigned short)
  <= sizeof(int)   == sizeof(unsigned int)
  <= sizeof(long)  == sizeof(unsigned long)
C ++ 11
 <= sizeof(long long) == sizeof(unsigned long long)

Los tamaños mínimos específicos para cada tipo no están dados por la norma. En su lugar, cada tipo tiene un rango mínimo de valores que puede admitir, que, como se especifica en § 3.9.1.3, se hereda del estándar C, en §5.2.4.2.1. El tamaño mínimo de cada tipo se puede inferir aproximadamente de este rango, al determinar el número mínimo de bits requeridos; tenga en cuenta que para cualquier plataforma dada, el rango real admitido de cualquier tipo puede ser mayor que el mínimo. Tenga en cuenta que para los tipos con signo, los rangos corresponden al complemento de uno, no al complemento de dos de uso más común; esto es para permitir que una gama más amplia de plataformas cumpla con el estándar.

Tipo Rango mínimo Bits mínimos requeridos
signed char -127 a 127 (- (2 7 - 1) a (2 7 - 1)) 8
unsigned char 0 a 255 (0 a 2 8 - 1) 8
signed short -32,767 a 32,767 (- (2 15 - 1) a (2 15 - 1)) dieciséis
unsigned short 0 a 65,535 (0 a 2 16 - 1) dieciséis
signed int -32,767 a 32,767 (- (2 15 - 1) a (2 15 - 1)) dieciséis
unsigned int 0 a 65,535 (0 a 2 16 - 1) dieciséis
signed long -2,147,483,647 a 2,147,483,647 (- (2 31 - 1) a (2 31 - 1)) 32
unsigned long 0 a 4,294,967,295 (0 a 2 32 - 1) 32
C ++ 11
Tipo Rango mínimo Bits mínimos requeridos
signed long long -9,223,372,036,854,775,807 a 9,223,372,036,854,775,807 (- (2 63 - 1) a (2 63 - 1)) 64
unsigned long long 0 a 18,446,744,073,709,551,615 (0 a 2 64 - 1) 64

Como se permite que cada tipo sea mayor que su requisito de tamaño mínimo, los tipos pueden diferir en tamaño entre las implementaciones. El ejemplo más notable de esto es con los modelos de datos de 64 bits LP64 y LLP64, donde los sistemas LLP64 (tales como Windows de 64 bits) tiene 32 bits ints y long s, y sistemas de LP64 (tales como Linux de 64 bits) tienen int s de 32 bits y s de 64 bits de long . Debido a esto, no se puede suponer que los tipos de enteros tengan un ancho fijo en todas las plataformas.

C ++ 11

Si se requieren tipos de enteros con ancho fijo, use tipos del encabezado <cstdint> , pero tenga en cuenta que el estándar hace que las implementaciones sean compatibles con los tipos de ancho exacto int8_t , int16_t , int32_t , int64_t , intptr_t , uint8_t , uint16_t , uint32_t , uint64_t y uintptr_t .

C ++ 11

Tamaño de char16_t y char32_t

Los tamaños de char16_t y char32_t están definidos por la implementación, como se especifica en el § 5.3.3.1, con las estipulaciones que figuran en el § 3.9.1.5:

  • char16_t es lo suficientemente grande como para representar cualquier unidad de código UTF-16, y tiene el mismo tamaño, firmeza y alineación que uint_least16_t ; por lo tanto, se requiere que tenga al menos 16 bits de tamaño.

  • char32_t es lo suficientemente grande como para representar cualquier unidad de código UTF-32, y tiene el mismo tamaño, firmeza y alineación que uint_least32_t ; por lo tanto, se requiere que tenga al menos 32 bits de tamaño.

Tamaño de bool

El tamaño de bool está definido en la implementación, y puede o no ser 1 .

Tamaño de wchar_t

wchar_t , como se especifica en § 3.9.1.5, es un tipo distinto, cuyo rango de valores puede representar cada unidad de código distinta del conjunto de caracteres extendido más grande entre los locales admitidos. Tiene el mismo tamaño, firmeza y alineación que uno de los otros tipos integrales, que se conoce como su tipo subyacente . El tamaño de este tipo está definido por la implementación, como se especifica en el § 5.3.3.1, y puede ser, por ejemplo, al menos 8, 16 o 32 bits; si un sistema admite Unicode, por ejemplo, se requiere que wchar_t tenga al menos 32 bits (una excepción a esta regla es Windows, donde wchar_t es de 16 bits por motivos de compatibilidad). Se hereda de la norma C90, ISO 9899: 1990 § 4.1.5, con solo una pequeña redacción.

Dependiendo de la implementación, el tamaño de wchar_t es a menudo, pero no siempre, de 8, 16 o 32 bits. Los ejemplos más comunes de estos son:

  • En sistemas similares a Unix y Unix, wchar_t es de 32 bits, y generalmente se usa para UTF-32.
  • En Windows, wchar_t es de 16 bits y se usa para UTF-16.
  • En un sistema que solo tiene soporte de 8 bits, wchar_t es de 8 bits.
C ++ 11

Si se desea compatibilidad con Unicode, se recomienda usar char para UTF-8, char16_t para UTF-16 o char32_t para UTF-32, en lugar de usar wchar_t .


Modelos de datos

Como se mencionó anteriormente, los anchos de los tipos de enteros pueden diferir entre plataformas. Los modelos más comunes son los siguientes, con tamaños especificados en bits:

Modelo int long puntero
LP32 (2/4/4) dieciséis 32 32
ILP32 (4/4/4) 32 32 32
LLP64 (4/4/8) 32 32 64
LP64 (4/8/8) 32 64 64

Fuera de estos modelos:

  • Windows de 16 bits utiliza LP32.
  • Los sistemas de 32 bits * nix (Unix, Linux, Mac OSX y otros sistemas operativos similares a Unix) y Windows usan ILP32.
  • Windows de 64 bits utiliza LLP64.
  • Los sistemas de 64 bits * nix utilizan LP64.

Tenga en cuenta, sin embargo, que estos modelos no se mencionan específicamente en la norma en sí.

Número de bits en un byte

En C ++, un byte es el espacio ocupado por un objeto char . La cantidad de bits en un byte viene dada por CHAR_BIT , que se define en climits y se requiere que sea al menos 8. Mientras que la mayoría de los sistemas modernos tienen bytes de 8 bits, y POSIX requiere que CHAR_BIT sea ​​exactamente 8, hay algunos sistemas donde CHAR_BIT es mayor que 8, es decir, un solo byte puede estar compuesto por 8, 16, 32 o 64 bits.

Valor numérico de un puntero

El resultado de convertir un puntero a un entero usando reinterpret_cast está definido por la implementación, pero "... no es sorprendente para aquellos que conocen la estructura de direccionamiento de la máquina subyacente".

int x = 42;
int* p = &x;
long addr = reinterpret_cast<long>(p);
std::cout << addr << "\n"; // prints some numeric address,
                           // probably in the architecture's native address format

Del mismo modo, el puntero obtenido por conversión de un entero también está definido por la implementación.

La forma correcta de almacenar un puntero como un entero es usando los tipos uintptr_t o intptr_t :

// `uintptr_t` was not in C++03. It's in C99, in <stdint.h>, as an optional type
#include <stdint.h>

uintptr_t uip;
C ++ 11
// There is an optional `std::uintptr_t` in C++11
#include <cstdint>

std::uintptr_t uip;

C ++ 11 hace referencia a C99 para la definición uintptr_t (estándar C99, 6.3.2.3):

un tipo de entero sin signo con la propiedad de que cualquier puntero válido para void se puede convertir a este tipo, luego se puede volver a convertir en puntero a void , y el resultado se comparará igual al puntero original.

Si bien, para la mayoría de las plataformas modernas, puede asumir un espacio de direcciones plano y que la aritmética en uintptr_t es equivalente a la aritmética en char * , es totalmente posible que una implementación realice una transformación al uintptr_t void * a uintptr_t siempre que la transformación pueda se invierte cuando se devuelve desde uintptr_t a void * .

Tecnicismos

  • En los sistemas intptr_t XSI (X / Open System Interfaces), se requieren los tipos intptr_t y uintptr_t , de lo contrario son opcionales .

  • En el sentido del estándar C, las funciones no son objetos; el estándar C no garantiza que uintptr_t pueda contener un puntero de función. De todos modos, la conformidad con POSIX (2.12.3) requiere que:

    Todos los tipos de punteros de función tendrán la misma representación que el puntero de tipo para anular. La conversión de un puntero de función a void * no alterará la representación. Un valor nulo * resultante de dicha conversión se puede convertir de nuevo al tipo de puntero de función original, utilizando una conversión explícita, sin pérdida de información.

  • C99 §7.18.1:

    Cuando se definen los nombres typedef que difieren solo en la ausencia o presencia de la u inicial, denotarán los tipos correspondientes firmados y no firmados como se describe en 6.2.5; una implementación que provea uno de estos tipos correspondientes también proporcionará el otro.

    uintptr_t podría tener sentido si quiere hacer cosas a los bits del puntero que no puede hacer con sensatez con un entero con signo.

Rangos de tipos numéricos

Los rangos de los tipos de enteros están definidos por la implementación. El encabezado <limits> proporciona la plantilla std::numeric_limits<T> que proporciona los valores mínimo y máximo de todos los tipos fundamentales. Los valores satisfacen las garantías proporcionadas por el estándar C a través de los <climits> y (> = C ++ 11) <cinttypes> .

  • std::numeric_limits<signed char>::min() es igual a SCHAR_MIN , que es menor o igual que -127.
  • std::numeric_limits<signed char>::max() es igual a SCHAR_MAX , que es mayor o igual a 127.
  • std::numeric_limits<unsigned char>::max() es igual a UCHAR_MAX , que es mayor o igual a 255.
  • std::numeric_limits<short>::min() es igual a SHRT_MIN , que es menor o igual que -32767.
  • std::numeric_limits<short>::max() es igual a SHRT_MAX , que es mayor o igual que 32767.
  • std::numeric_limits<unsigned short>::max() es igual a USHRT_MAX , que es mayor o igual a 65535.
  • std::numeric_limits<int>::min() es igual a INT_MIN , que es menor o igual que -32767.
  • std::numeric_limits<int>::max() es igual a INT_MAX , que es mayor o igual a 32767.
  • std::numeric_limits<unsigned int>::max() es igual a UINT_MAX , que es mayor o igual a 65535.
  • std::numeric_limits<long>::min() es igual a LONG_MIN , que es menor o igual a -2147483647.
  • std::numeric_limits<long>::max() es igual a LONG_MAX , que es mayor o igual que 2147483647.
  • std::numeric_limits<unsigned long>::max() es igual a ULONG_MAX , que es mayor o igual que 4294967295.
C ++ 11
  • std::numeric_limits<long long>::min() es igual a LLONG_MIN , que es menor o igual que -9223372036854775807.
  • std::numeric_limits<long long>::max() es igual a LLONG_MAX , que es mayor o igual que 9223372036854775807.
  • std::numeric_limits<unsigned long long>::max() es igual a ULLONG_MAX , que es mayor o igual que 18446744073709551615.

Para los tipos de punto flotante T , max() es el valor finito máximo, mientras que min() es el valor normalizado positivo mínimo. Se proporcionan miembros adicionales para los tipos de punto flotante, que también están definidos por la implementación pero satisfacen ciertas garantías proporcionadas por el estándar C a través del encabezado <cfloat> .

  • El digits10 da el número de dígitos decimales de precisión.
    • std::numeric_limits<float>::digits10 es igual a FLT_DIG , que es al menos 6.
    • std::numeric_limits<double>::digits10 es igual a DBL_DIG , que es al menos 10.
    • std::numeric_limits<long double>::digits10 es igual a LDBL_DIG , que es al menos 10.
  • El miembro min_exponent10 es el E negativo mínimo tal que 10 a la potencia E es normal.
    • std::numeric_limits<float>::min_exponent10 es igual a FLT_MIN_10_EXP , que es como máximo -37.
    • std::numeric_limits<double>::min_exponent10 es igual a DBL_MIN_10_EXP , que es como máximo -37. std::numeric_limits<long double>::min_exponent10 es igual a LDBL_MIN_10_EXP , que es como máximo -37.
  • El miembro max_exponent10 es el E máximo, de modo que 10 para la potencia E es finito.
    • std::numeric_limits<float>::max_exponent10 es igual a FLT_MIN_10_EXP , que es al menos 37.
    • std::numeric_limits<double>::max_exponent10 es igual a DBL_MIN_10_EXP , que es al menos 37.
    • std::numeric_limits<long double>::max_exponent10 es igual a LDBL_MIN_10_EXP , que es al menos 37.
  • Si el miembro is_iec559 es verdadero, el tipo cumple con IEC 559 / IEEE 754 y, por lo tanto, su rango está determinado por esa norma.

Representación del valor de los tipos de punto flotante

El estándar requiere que el long double proporcione al menos la misma precisión que el double , lo que proporciona al menos la misma precisión que el float ; y que un long double puede representar cualquier valor que un double pueda representar, mientras que un double puede representar cualquier valor que un float pueda representar. Los detalles de la representación están, sin embargo, definidos por la implementación.

Para un tipo de punto flotante T , std::numeric_limits<T>::radix especifica el radix utilizado por la representación de T

Si std::numeric_limits<T>::is_iec559 es verdadero, entonces la representación de T coincide con uno de los formatos definidos por IEC 559 / IEEE 754.

Desbordamiento al convertir de entero a entero con signo

Cuando un entero con signo o sin signo se convierte en un tipo de entero con signo y su valor no se puede representar en el tipo de destino, el valor producido se define por la implementación. Ejemplo:

// Suppose that on this implementation, the range of signed char is -128 to +127 and
// the range of unsigned char is 0 to 255
int x = 12345;
signed char sc = x;   // sc has an implementation-defined value
unsigned char uc = x; // uc is initialized to 57 (i.e., 12345 modulo 256)

Tipo subyacente (y, por tanto, tamaño) de una enumeración

Si el tipo subyacente no se especifica explícitamente para un tipo de enumeración sin ámbito, se determina de una manera definida por la implementación.

enum E {
    RED,
    GREEN,
    BLUE,
};
using T = std::underlying_type<E>::type; // implementation-defined

Sin embargo, el estándar requiere que el tipo subyacente de una enumeración no sea mayor que int menos que int y unsigned int no puedan representar todos los valores de la enumeración. Por lo tanto, en el código anterior, T podría ser int , unsigned int , o short , pero no long long , para dar algunos ejemplos.

Tenga en cuenta que una enumeración tiene el mismo tamaño (según lo devuelto por sizeof ) que su tipo subyacente.



Modified text is an extract of the original Stack Overflow Documentation
Licenciado bajo CC BY-SA 3.0
No afiliado a Stack Overflow