c++ - tipo - unsigned char c
¿Cuál es la diferencia entre un int y un long en C++? (9)
Corrígeme si estoy equivocado,
int es 4 bytes, con un rango de valores de -2,147,483,648 a 2,147,483,647 (2 ^ 31)
long tiene 4 bytes, con un rango de valores de -2,147,483,648 a 2,147,483,647 (2 ^ 31)
¿Cuál es la diferencia en C ++? ¿Se pueden usar indistintamente?
Al compilar para x64, la diferencia entre int y long está entre 0 y 4 bytes, según el compilador que utilice.
GCC usa el modelo LP64, lo que significa que las entradas son de 32 bits, pero las de 64 bits en el modo de 64 bits.
MSVC, por ejemplo, utiliza el modelo LLP64, lo que significa que tanto las entradas como las longitudes son de 32 bits, incluso en el modo de 64 bits.
Como señala Kevin Haines, las entradas tienen el tamaño natural sugerido por el entorno de ejecución, que debe ajustarse a INT_MIN e INT_MAX.
El estándar C89 establece que UINT_MAX
debe ser al menos 2 ^ 16-1, USHRT_MAX
2 ^ 16-1 y ULONG_MAX
2 ^ 32-1. Eso hace un conteo de bits de al menos 16 para short e int, y 32 para long. Para char declara explícitamente que debe tener al menos 8 bits ( CHAR_BIT
). C ++ hereda esas reglas para el archivo limits.h, entonces en C ++ tenemos los mismos requisitos fundamentales para esos valores. Sin embargo, no debe derivarse de que ese int sea al menos de 2 bytes. Teóricamente, char, int y long podrían ser 1 byte, en cuyo caso CHAR_BIT
debe ser al menos 32. Solo recuerda que "byte" siempre tiene el tamaño de un carácter, por lo que si el carácter es más grande, un byte no es solo 8 bits nunca más.
Confiar en la implementación del proveedor de compiladores de tamaños de tipos primitivos VUELVE a atormentarlo si alguna vez compila su código en otra arquitectura de máquina, sistema operativo u otro compilador de proveedor.
La mayoría de los proveedores de compiladores proporcionan un archivo de encabezado que define los tipos primitivos con tamaños de tipo explict. Estos tipos primitivos deben usarse cuando alguna vez el código pueda ser potencialmente portado a otro compilador (léalo como SIEMPRE en CADA instancia). Por ejemplo, la mayoría de los compiladores de UNIX tienen int8_t uint8_t int16_t int32_t uint32_t
. Microsoft tiene INT8 UINT8 INT16 UINT16 INT32 UINT32
. Prefiero el int8 uint8 int16 uint16 int32 uint32
Borland / CodeGear. Estos nombres también dan un pequeño recordatorio del tamaño / rango del valor deseado.
Durante años utilicé los nombres de tipos primitivos explícitos de Borland y #include
el siguiente archivo de encabezado C / C ++ (primitive.h) que intenta definir los tipos primitivos explícitos con estos nombres para cualquier compilador C / C ++ (este archivo de encabezado podría no serlo cubren todos los compiladores, pero cubren varios compiladores que he usado en Windows, UNIX y Linux, pero (aún) no define tipos de 64 bits).
#ifndef primitiveH
#define primitiveH
// Header file primitive.h
// Primitive types
// For C and/or C++
// This header file is intended to define a set of primitive types
// that will always be the same number bytes on any operating operating systems
// and/or for several popular C/C++ compiler vendors.
// Currently the type definitions cover:
// Windows (16 or 32 bit)
// Linux
// UNIX (HP/US, Solaris)
// And the following compiler vendors
// Microsoft, Borland/Imprise/CodeGear, SunStudio, HP/UX
// (maybe GNU C/C++)
// This does not currently include 64bit primitives.
#define float64 double
#define float32 float
// Some old C++ compilers didn''t have bool type
// If your compiler does not have bool then add emulate_bool
// to your command line -D option or defined macros.
#ifdef emulate_bool
# ifdef TVISION
# define bool int
# define true 1
# define false 0
# else
# ifdef __BCPLUSPLUS__
//BC++ bool type not available until 5.0
# define BI_NO_BOOL
# include <classlib/defs.h>
# else
# define bool int
# define true 1
# define false 0
# endif
# endif
#endif
#ifdef __BCPLUSPLUS__
# include <systypes.h>
#else
# ifdef unix
# ifdef hpux
# include <sys/_inttypes.h>
# endif
# ifdef sun
# include <sys/int_types.h>
# endif
# ifdef linux
# include <idna.h>
# endif
# define int8 int8_t
# define uint8 uint8_t
# define int16 int16_t
# define int32 int32_t
# define uint16 uint16_t
# define uint32 uint32_t
# else
# ifdef _MSC_VER
# include <BaseTSD.h>
# define int8 INT8
# define uint8 UINT8
# define int16 INT16
# define int32 INT32
# define uint16 UINT16
# define uint32 UINT32
# else
# ifndef OWL6
// OWL version 6 already defines these types
# define int8 char
# define uint8 unsigned char
# ifdef __WIN32_
# define int16 short int
# define int32 long
# define uint16 unsigned short int
# define uint32 unsigned long
# else
# define int16 int
# define int32 long
# define uint16 unsigned int
# define uint32 unsigned long
# endif
# endif
# endif
# endif
#endif
typedef int8 sint8;
typedef int16 sint16;
typedef int32 sint32;
typedef uint8 nat8;
typedef uint16 nat16;
typedef uint32 nat32;
typedef const char * cASCIIz; // constant null terminated char array
typedef char * ASCIIz; // null terminated char array
#endif
//primitive.h
Depende de la implementación.
Por ejemplo, en Windows son iguales, pero por ejemplo en los sistemas Alpha, un largo era de 64 bits, mientras que un int era de 32 bits. Este article cubre las reglas para el compilador Intel C ++ en plataformas variables. Para resumir:
OS arch size
Windows IA-32 4 bytes
Windows Intel 64 4 bytes
Windows IA-64 4 bytes
Linux IA-32 4 bytes
Linux Intel 64 8 bytes
Linux IA-64 8 bytes
Mac OS X IA-32 4 bytes
Mac OS X Intel 64 8 bytes
Depende de tu compilador. Se le garantiza que una longitud será al menos tan grande como un int, pero no se le garantiza que continuará.
El estándar C ++ lo dice así:
3.9.1, §2:
Hay cinco tipos de entero con signo: "signed char", "short int", "int", "long int" y "long long int". En esta lista, cada tipo proporciona al menos tanto almacenamiento como los que lo preceden en la lista. Las aplicaciones simples tienen el tamaño natural sugerido por la arquitectura del entorno de ejecución (44); los otros tipos de entero con signo se proporcionan para satisfacer necesidades especiales.
(44) es decir, lo suficientemente grande como para contener cualquier valor en el rango de INT_MIN e INT_MAX, como se define en el encabezado
<climits>
.
La conclusión: depende de la arquitectura en la que estés trabajando. Cualquier otra suposición es falsa.
En su mayor parte, el número de bytes y el rango de valores viene determinado por la arquitectura de la CPU, no por C ++. Sin embargo, C ++ establece requisitos mínimos, que se explicaron adecuadamente y Martin York solo cometió algunos errores.
La razón por la que no puede usar int y long indistintamente es porque no siempre tienen la misma longitud. C se inventó en un PDP-11 donde un byte tenía 8 bits, int tenía dos bytes y podía manejarse directamente mediante instrucciones de hardware. Dado que los programadores de C a menudo necesitaban aritmética de cuatro bytes, se inventó el tiempo y tenía cuatro bytes, manejados por las funciones de la biblioteca. Otras máquinas tenían diferentes especificaciones. El estándar C impuso algunos requisitos mínimos.
La única garantía que tienes es:
sizeof(char) == 1
sizeof(char) <= sizeof(short) <= sizeof(int) <= sizeof(long) <= sizeof(long long)
// FROM @KTC. The C++ standard also has:
sizeof(signed char) == 1
sizeof(unsigned char) == 1
// NOTE: These size are not specified explicitly in the standard.
// They are implied by the minimum/maximum values that MUST be supported
// for the type. These limits are defined in limits.h
sizeof(short) * CHAR_BIT >= 16
sizeof(int) * CHAR_BIT >= 16
sizeof(long) * CHAR_BIT >= 32
sizeof(long long) * CHAR_BIT >= 64
CHAR_BIT >= 8 // Number of bits in a byte
Ver también: ¿Se garantiza por long
que sea de al menos 32 bits?
La especificación C ++ en sí (versión antigua pero lo suficientemente buena para esto) deja esto abierto.
Hay cuatro tipos de entero con signo: ''
signed char
'', ''short int
'', ''int
'' y ''long int
''. En esta lista, cada tipo proporciona al menos tanto almacenamiento como los que lo preceden en la lista. Las aplicaciones simples tienen el tamaño natural sugerido por la arquitectura del entorno de ejecución *;[Nota al pie: es decir, lo suficientemente grande como para contener cualquier valor en el rango de INT_MIN e INT_MAX, como se define en el encabezado
<climits>
. --- end foonote]