我正在寻找有关基本 C++ 类型大小的详细信息。我知道这取决于架构(16 位、32 位、64 位)和编译器。
但是 C++ 有什么标准吗?
我在 32 位架构上使用 Visual Studio 2008。这是我得到的:
char : 1 byte
short : 2 bytes
int : 4 bytes
long : 4 bytes
float : 4 bytes
double: 8 bytes
我试图在下面找到说明 char
、short
、int
、long
、double
、float
(以及我没有想到的其他类型)大小的可靠信息,但没有取得多大成功不同的架构和编译器。
int16_t
、int32_t
和 int64_t
(如果我没记错的话,需要包含 iostream
)。这有什么好处 int64_t 在 32 位系统上不应该有问题(但这会影响性能)。
<cstdint>
中定义的,而不是在 <iostream>
中。
C++ 标准没有以字节为单位指定整数类型的大小,但它指定了它们必须能够保持的最小范围。您可以从所需范围推断出最小大小。您可以从中推断出最小大小(以字节为单位)以及 defines the number of bits in a byte 的 CHAR_BIT
宏的值。除了最不起眼的平台之外,它是 8 个,而且不能少于 8 个。
char
的另一个约束是它的大小始终为 1 字节或 CHAR_BIT
位(因此得名)。这在标准中明确说明。
C 标准是 C++ 标准的规范性参考,因此即使它没有明确说明这些要求,C++ 也需要最小范围 required by the C standard(第 22 页),这与那些相同来自 MSDN 上的数据类型范围:
有符号字符:-127 到 127(注意,不是 -128 到 127;这适用于 1 的补码和符号和幅度平台) 无符号字符:0 到 255 “普通”字符:与有符号字符或无符号字符的范围相同,实现-defined signed short: -32767 to 32767 unsigned short: 0 to 65535 signed int: -32767 to 32767 unsigned int: 0 to 65535 signed long: -2147483647 to 2147483647 unsigned long: 0 to 4294967295 signed long long: -9223372036854775807 to 9223372036854775807 unsigned长长:0到18446744073709551615
C++(或 C)实现可以将类型的大小(以字节 sizeof(type)
为单位)定义为任何值,只要
表达式 sizeof(type) * CHAR_BIT 计算为足够高的位数以包含所需的范围,并且类型的排序仍然有效(例如 sizeof(int) <= sizeof(long))。
综上所述,我们保证:
char、signed char 和 unsigned char 至少为 8 位
有符号短、无符号短、有符号整数和无符号整数至少为 16 位
signed long 和 unsigned long 至少为 32 位
signed long long 和 unsigned long long 至少为 64 位
不保证 float
或 double
的大小,除非 double
提供的精度至少与 float
一样高。
实际特定于实现的范围可以在 C 中的 <limits.h>
标头或 C++ 中的 <climits>
中找到(或者更好的是,<limits>
标头中的模板化 std::numeric_limits
)。
例如,您将通过以下方式找到 int
的最大范围:
C:
#include <limits.h>
const int min_int = INT_MIN;
const int max_int = INT_MAX;
C++:
#include <limits>
const int min_int = std::numeric_limits<int>::min();
const int max_int = std::numeric_limits<int>::max();
对于 32 位系统,“事实上的”标准是 ILP32 — 即 int
、long
和指针都是 32 位量。
对于 64 位系统,主要的 Unix“事实上的”标准是 LP64 — long
和指针是 64 位(但 int
是 32 位)。 Windows 64 位标准是 LLP64 — long long
和指针是 64 位(但 long
和 int
都是 32 位)。
曾经,一些 Unix 系统使用 ILP64 组织。
这些事实上的标准都没有被 C 标准 (ISO/IEC 9899:1999) 立法,但都被它所允许。
而且,根据定义,sizeof(char)
是 1
,尽管在 Perl 配置脚本中进行了测试。
请注意,有些机器 (Crays) 的 CHAR_BIT
远大于 8。这意味着 IIRC,sizeof(int)
也是 1,因为 char
和 int
都是 32 位的。
[u]int32_t
或类似的,如果您想要 64 位使用 [u]int64_t
...如果您没有标题,请下载或制作一个,最好使用此类类型的编译时选择或静态断言来验证大小。 pubs.opengroup.org/onlinepubs/009695299/basedefs/stdint.h.html 如果精确尺寸不是那么重要,而您只关心它们至少有那么大,那么您的建议适用于常见的现代 PC/服务器平台。
*c
的函数 int get_char(FILE *fp, char *c)
。
在实践中没有这样的事情。通常,您可以期望 std::size_t
表示当前架构上的无符号本机整数大小。即 16 位、32 位或 64 位,但并非总是如此,正如对此答案的评论中所指出的那样。
就所有其他内置类型而言,它实际上取决于编译器。以下是从最新 C++ 标准的当前工作草案中摘录的两段:
有五种标准有符号整数类型:signed char、short int、int、long int 和 long long int。在此列表中,每种类型提供的存储空间至少与列表中它前面的类型一样多。对于每一种标准的有符号整数类型,都存在对应的(但不同的)标准无符号整数类型:unsigned char、unsigned short int、unsigned int、unsigned long int 和 unsigned long long int,每一种都占用相同数量的存储和具有相同的对齐要求。
如果你愿意,你可以静态地(编译时)断言这些基本类型的大小。如果 sizeof 假设发生变化,它将提醒人们考虑移植您的代码。
有标准。
C90 标准要求
sizeof(short) <= sizeof(int) <= sizeof(long)
C99 标准要求
sizeof(short) <= sizeof(int) <= sizeof(long) <= sizeof(long long)
Here is the C99 specifications。第 22 页详细介绍了不同整数类型的大小。
以下是 Windows 平台的 int 类型大小(位):
Type C99 Minimum Windows 32bit
char 8 8
short 16 16
int 16 32
long 32 32
long long 64 64
如果您关心可移植性,或者您希望类型的名称反映大小,您可以查看标题 <inttypes.h>
,其中可以使用以下宏:
int8_t
int16_t
int32_t
int64_t
int8_t
保证为 8 位,int16_t
保证为 16 位,以此类推。
sizeof(long) < sizeof(long long)
而不是对称的 sizeof(long) <= sizeof(long long)
?
如果您需要固定大小的类型,请使用 stdint.h 中定义的类型,如 uint32_t(无符号整数 32 位)。它们在 C99 中指定。
CHAR_BIT == 16
的平台将没有 int8_t
。任何不使用补码的平台都不会有 any (因为标准要求补码)。
uint16_t
,除非它们还具有范围为 -32768 到 32767(含)的二进制补码类型。我认为如果一个实现的 16 位有符号整数类型不满足要求(很可能是因为位模式 0x8000 并不总是像紧邻 -32767 的整数值那样表现),那么让它定义 {1 } 而不定义 int16_t
,而不是禁止它声明。
更新:C++11 将 TR1 中的类型正式引入标准:
长长整数
unsigned long long int
以及 <cstdint>
中的“大小”类型
int8_t
int16_t
int32_t
int64_t
(和未签名的同行)。
此外,您还可以获得:
int_least8_t
int_least16_t
int_least32_t
int_least64_t
加上未签名的同行。
这些类型表示具有至少指定位数的最小整数类型。同样,有至少指定位数的“最快”整数类型:
int_fast8_t
int_fast16_t
int_fast32_t
int_fast64_t
加上未签名的版本。
“快速”的含义(如果有的话)取决于实施。对于所有目的,它也不必是最快的。
C++ Standard 是这样说的:
3.9.1,§2:
有五种有符号整数类型:“signed char”、“short int”、“int”、“long int”和“long long int”。在此列表中,每种类型提供的存储空间至少与列表中它前面的类型一样多。普通整数具有执行环境架构所建议的自然大小(44);提供其他有符号整数类型以满足特殊需要。 (44) 即大到足以包含 INT_MIN 和 INT_MAX 范围内的任何值,如标题
结论:这取决于您正在处理的架构。任何其他假设都是错误的。
不,没有字体大小的标准。标准只要求:
sizeof(short int) <= sizeof(int) <= sizeof(long int)
如果您想要固定大小的变量,您可以做的最好的事情是使用这样的宏:
#ifdef SYSTEM_X
#define WORD int
#else
#define WORD long int
#endif
然后你可以使用 WORD 来定义你的变量。不是我喜欢这种方式,而是最便携的方式。
#include <boost/cstdint.hpp>
对于浮点数 there is a standard (IEEE754):浮点数是 32 位,双精度数是 64。这是硬件标准,而不是 C++ 标准,因此编译器理论上可以将浮点数和双精度数定义为其他大小,但实际上我从未见过使用任何不同的架构。
double
的大小与 float
相同(而 int
与 char
相同,均为 16 位)。但他们有一个 64 位的 long double
。
我们可以为类型定义同义词,这样我们就可以创建自己的“标准”。
在 sizeof(int) == 4 的机器上,我们可以定义:
typedef int int32;
int32 i;
int32 j;
...
因此,当我们将代码转移到实际上 long int 的大小为 4 的另一台机器上时,我们可以重新定义 int 的单次出现。
typedef long int int32;
int32 i;
int32 j;
...
<stdint.h>
(C99 及更高版本,以及采用 C99 版本的 C 库的任何 C++ 标准),这不是必需的。
有一个标准,它在各种标准文件(ISO、ANSI 等)中都有规定。
维基百科有一个很棒的页面,解释了各种类型和它们可以存储的最大值:Integer in Computer Science.
然而,即使使用标准 C++ 编译器,您也可以使用以下代码片段相对轻松地找到:
#include <iostream>
#include <limits>
int main() {
// Change the template parameter to the various different types.
std::cout << std::numeric_limits<int>::max() << std::endl;
}
std::numeric_limits 的文档可在 Roguewave 中找到。它包括大量其他命令,您可以调用它来找出各种限制。这可以与任何传达大小的任意类型一起使用,例如 std::streamsize。
约翰的答案包含最好的描述,因为这些是保证成立的。无论您在哪个平台上,还有另一个很好的页面,其中更详细地说明了每种类型必须包含多少位:int types,在标准中定义。
我希望这有帮助!
当涉及到不同架构和不同编译器的内置类型时,只需使用编译器在您的架构上运行以下代码以查看它的输出。下面显示了我的 Ubuntu 13.04 (Raring Ringtail) 64 位 g++4.7.3 输出。另请注意以下回答的内容,这就是输出如此排序的原因:
“有五种标准有符号整数类型:signed char、short int、int、long int 和 long long int。在此列表中,每种类型提供的存储空间至少与列表中它前面的类型一样多。”
#include <iostream>
int main ( int argc, char * argv[] )
{
std::cout<< "size of char: " << sizeof (char) << std::endl;
std::cout<< "size of short: " << sizeof (short) << std::endl;
std::cout<< "size of int: " << sizeof (int) << std::endl;
std::cout<< "size of long: " << sizeof (long) << std::endl;
std::cout<< "size of long long: " << sizeof (long long) << std::endl;
std::cout<< "size of float: " << sizeof (float) << std::endl;
std::cout<< "size of double: " << sizeof (double) << std::endl;
std::cout<< "size of pointer: " << sizeof (int *) << std::endl;
}
size of char: 1
size of short: 2
size of int: 4
size of long: 8
size of long long: 8
size of float: 4
size of double: 8
size of pointer: 8
sizeof(char)
不应包含在内。
您可以使用:
cout << "size of datatype = " << sizeof(datatype) << endl;
datatype = int
、long int
等。您将能够看到您键入的任何数据类型的大小。
如前所述,大小应反映当前架构。如果您想了解您当前的编译器是如何处理事情的,您可以在 limits.h
中找到一个高峰。
如果您对纯 C++ 解决方案感兴趣,我使用模板和仅 C++ 标准代码在编译时根据其位大小定义类型。这使得解决方案可以跨编译器移植。
背后的想法非常简单:创建一个包含 char、int、short、long、long long 类型(有符号和无符号版本)的列表,然后扫描列表并使用 numeric_limits 模板选择具有给定大小的类型。
包括这个头你有 8 种类型 stdtype::int8、stdtype::int16、stdtype::int32、stdtype::int64、stdtype::uint8、stdtype::uint16、stdtype::uint32、stdtype::uint64。
如果某些类型无法表示,它将被评估为 stdtype::null_type 也在该标头中声明。
以下代码不提供任何保证,请仔细检查。我也是元编程的新手,请随意编辑和更正此代码。用 DevC++ 测试(所以 gcc 版本大约是 3.5)
#include <limits>
namespace stdtype
{
using namespace std;
/*
* THIS IS THE CLASS USED TO SEMANTICALLY SPECIFY A NULL TYPE.
* YOU CAN USE WHATEVER YOU WANT AND EVEN DRIVE A COMPILE ERROR IF IT IS
* DECLARED/USED.
*
* PLEASE NOTE that C++ std define sizeof of an empty class to be 1.
*/
class null_type{};
/*
* Template for creating lists of types
*
* T is type to hold
* S is the next type_list<T,S> type
*
* Example:
* Creating a list with type int and char:
* typedef type_list<int, type_list<char> > test;
* test::value //int
* test::next::value //char
*/
template <typename T, typename S> struct type_list
{
typedef T value;
typedef S next;
};
/*
* Declaration of template struct for selecting a type from the list
*/
template <typename list, int b, int ctl> struct select_type;
/*
* Find a type with specified "b" bit in list "list"
*
*
*/
template <typename list, int b> struct find_type
{
private:
//Handy name for the type at the head of the list
typedef typename list::value cur_type;
//Number of bits of the type at the head
//CHANGE THIS (compile time) exp TO USE ANOTHER TYPE LEN COMPUTING
enum {cur_type_bits = numeric_limits<cur_type>::digits};
public:
//Select the type at the head if b == cur_type_bits else
//select_type call find_type with list::next
typedef typename select_type<list, b, cur_type_bits>::type type;
};
/*
* This is the specialization for empty list, return the null_type
* OVVERRIDE this struct to ADD CUSTOM BEHAVIOR for the TYPE NOT FOUND case
* (ie search for type with 17 bits on common archs)
*/
template <int b> struct find_type<null_type, b>
{
typedef null_type type;
};
/*
* Primary template for selecting the type at the head of the list if
* it matches the requested bits (b == ctl)
*
* If b == ctl the partial specified templated is evaluated so here we have
* b != ctl. We call find_type on the next element of the list
*/
template <typename list, int b, int ctl> struct select_type
{
typedef typename find_type<typename list::next, b>::type type;
};
/*
* This partial specified templated is used to select top type of a list
* it is called by find_type with the list of value (consumed at each call)
* the bits requested (b) and the current type (top type) length in bits
*
* We specialice the b == ctl case
*/
template <typename list, int b> struct select_type<list, b, b>
{
typedef typename list::value type;
};
/*
* These are the types list, to avoid possible ambiguity (some weird archs)
* we kept signed and unsigned separated
*/
#define UNSIGNED_TYPES type_list<unsigned char, \
type_list<unsigned short, \
type_list<unsigned int, \
type_list<unsigned long, \
type_list<unsigned long long, null_type> > > > >
#define SIGNED_TYPES type_list<signed char, \
type_list<signed short, \
type_list<signed int, \
type_list<signed long, \
type_list<signed long long, null_type> > > > >
/*
* These are acutally typedef used in programs.
*
* Nomenclature is [u]intN where u if present means unsigned, N is the
* number of bits in the integer
*
* find_type is used simply by giving first a type_list then the number of
* bits to search for.
*
* NB. Each type in the type list must had specified the template
* numeric_limits as it is used to compute the type len in (binary) digit.
*/
typedef find_type<UNSIGNED_TYPES, 8>::type uint8;
typedef find_type<UNSIGNED_TYPES, 16>::type uint16;
typedef find_type<UNSIGNED_TYPES, 32>::type uint32;
typedef find_type<UNSIGNED_TYPES, 64>::type uint64;
typedef find_type<SIGNED_TYPES, 7>::type int8;
typedef find_type<SIGNED_TYPES, 15>::type int16;
typedef find_type<SIGNED_TYPES, 31>::type int32;
typedef find_type<SIGNED_TYPES, 63>::type int64;
}
正如其他人所回答的那样,“标准”将大部分细节都保留为“实现定义”,并且仅声明“char”类型至少为“char_bis”宽,并且“char <= short <= int <= long < = long long”(float 和 double 与 IEEE 浮点标准非常一致,long double 通常与 double 相同——但在更多当前的实现中可能更大)。
没有非常具体和精确的值的部分原因是因为像 C/C++ 这样的语言被设计为可移植到大量硬件平台——包括“char”字长可能为 4 位的计算机系统或 7 位,甚至是普通家庭计算机用户所接触的“8-/16-/32-/64 位”计算机之外的某个值。 (这里的字长意味着系统正常运行的位宽——同样,它并不总是像家庭计算机用户所期望的那样总是 8 位。)
如果您确实需要特定位数的对象(在表示整数值的一系列位的意义上),大多数编译器都有一些指定方法;但它通常不可移植,即使在 ame 公司制造的编译器之间,但针对不同平台也是如此。一些标准和实践(尤其是 limits.h 等)非常普遍,以至于大多数编译器都支持确定特定值范围的最佳拟合类型,但不支持确定使用的位数。 (也就是说,如果您知道您需要保存 0 到 127 之间的值,您可以确定您的编译器支持 8 位的“int8”类型,它足以容纳所需的全部范围,但不像"int7" 类型,它与 7 位完全匹配。)
注意:许多 Un*x 源代码包使用“./configure”脚本,该脚本将探测编译器/系统的功能并输出合适的 Makefile 和 config.h。您可能会检查其中一些脚本以了解它们如何工作以及它们如何探测编译器/系统功能,并遵循它们的引导。
我注意到这里的所有其他答案几乎都集中在整数类型上,而提问者还询问了浮点数。
我不认为 C++ 标准需要它,但现在最常见平台的编译器通常遵循 IEEE754 标准的浮点数。该标准指定了四种类型的二进制浮点(以及一些 BCD 格式,我从未见过 C++ 编译器支持这些格式):
半精度 (binary16) - 11 位有效数,指数范围 -14 到 15
单精度 (binary32) - 24 位有效数,指数范围 -126 到 127
双精度 (binary64) - 53 位有效数,指数范围 -1022 到 1023
四倍精度 (binary128) - 113 位有效数,指数范围 -16382 到 16383
那么,它如何映射到 C++ 类型呢?通常 float
使用单精度;因此,sizeof(float) = 4
。然后 double
使用双精度(我相信这就是名称 double
的来源),而 long double
可能是双精度或四精度(在我的系统上是四精度,但在 32 位系统上可能是双精度) .我不知道任何提供半精度浮点的编译器。
总而言之,这是通常的:
大小(浮动)= 4
大小(双)= 8
sizeof(long double) = 8 或 16
unsigned char bits = sizeof(X) << 3;
其中 X
是 char
、int
、long
等。将为您提供 X
的大小(以位为单位)。
sizeof(type)*CHAR_BIT
个持有
CHAR_BIT
被保证为 8 位,<< 3
也只是编写 * 8
或 * CHAR_BIT
的一种混淆方式。
来自 Alex B C++ 标准没有以字节为单位指定整数类型的大小,但它指定了它们必须能够保持的最小范围。您可以从所需范围推断出最小大小。您可以从中推断出以字节为单位的最小大小以及定义字节中位数的 CHAR_BIT 宏的值(除了最晦涩的平台,它是 8,并且不能小于 8)。
char 的另一个约束是它的大小始终为 1 个字节,或 CHAR_BIT 位(因此得名)。
标准要求的最小范围(第 22 页)为:
和 MSDN 上的数据类型范围:
有符号字符:-127 到 127(注意,不是 -128 到 127;这适用于 1 的补码平台) 无符号字符:0 到 255 “普通”字符:-127 到 127 或 0 到 255(取决于默认的字符符号) short: -32767 to 32767 unsigned short: 0 to 65535 signed int: -32767 to 32767 unsigned int: 0 to 65535 signed long: -2147483647 to 2147483647 unsigned long: 0 to 4294967295 signed long long: -9223372036854775807 to 9223372036854775807 unsigned long long: 0 到 18446744073709551615 C++(或 C)实现可以将类型的大小(以字节 sizeof(type) 为单位)定义为任何值,只要
表达式 sizeof(type) * CHAR_BIT 计算为足以包含所需范围的位数,并且类型的排序仍然有效(例如 sizeof(int) <= sizeof(long))。实际特定于实现的范围可以在 C 或 C++ 中的 header 中找到(或者更好的是,在 header 中模板化 std::numeric_limits )。
例如,您将通过以下方式找到 int 的最大范围:
C:
#include <limits.h>
const int min_int = INT_MIN;
const int max_int = INT_MAX;
C++:
#include <limits>
const int min_int = std::numeric_limits<int>::min();
const int max_int = std::numeric_limits<int>::max();
这是正确的,但是,您说的也是正确的: char : 1 byte short : 2 bytes int : 4 bytes long : 4 bytes float : 4 bytes double : 8 bytes
因为 32 位架构仍然是默认和最常用的,并且自 32 位之前的内存可用较少的日子以来,它们一直保持这些标准大小,并且为了向后兼容性和标准化,它保持不变。甚至 64 位系统也倾向于使用这些并进行扩展/修改。请参考此以获取更多信息:
http://en.cppreference.com/w/cpp/language/types
正如您所提到的 - 它在很大程度上取决于编译器和平台。为此,请检查 ANSI 标准,http://home.att.net/~jackklein/c/inttypes.html
这是 Microsoft 编译器的编译器:Data Type Ranges。
在 64 位机器上:
int: 4
long: 8
long long: 8
void*: 8
size_t: 8
int
是 8 个字节,但不能保证另一个。没有什么说 char
应该只有 8 位。即使它是 64 位,也允许有 sizeof(void*)==4
。
根据大小,有四种类型的整数:
短整数:2字节
长整数:4 字节
long long 整数:8 字节
整数:取决于编译器(16 位、32 位或 64 位)
short
、int
和 long
所有 32 位整数。
int
,而不是“整数”一词。
char
”,而不是通常的含义。