在C语言中,每一个变量都有两个属性:数据类型和存储类型。
- 数据类型即常说的字符型、整型、浮点型;
- 存储类型则指变量在内存中的存储方式,它决定了变量的作用域和生存期。
变量的数据类型(Fundamental Type)
学了C然后C++,然后 Windows/MFC,然后是C#,其中数据类型很多,由基本类型衍生的typedef类型也N多。
熟知基本数据类型是我们正确表达实际问题中各种数据的前提,因此我分类总结了一下 C/C++/Windows /C# 基本数据类型,以便日后查阅。
参考 GNU 的 Data Type Measurements 和 MSDN 的 Fundamental Types (C++) & Data Type Ranges & C++ Type System (Modern C++) 相关文档。
C/C++ 基本数据类型
Type
Size
值域(limit)
无值型void
0 byte
无值域
布尔型bool
1 byte
true/false
有符号短整型 short [int] /signed short [int]
2 byte(__SIZEOF_SHORT__)
[SHRT_MIN,SHRT_MAX]
无符号短整型 unsigned short [int]
2 byte
[0,USHRT_MAX]
有符号整型 int /signed [int]
4 byte(__SIZEOF_INT__)
[INT_MIN,INT_MAX]
无符号整型 unsigned [int]
4 byte
[0,UINT_MAX]
有符号长整型 long [int]/signed long [int]
4 byte/8 byte(__SIZEOF_LONG__)
[LONG_MIN,LONG_MAX]
无符号长整型 unsigned long [int]
4 byte/8 byte
[0,ULONG_MAX]
long long
8 byte(__SIZEOF_LONG_LONG__)
[LLONG_MIN,LLONG_MAX]
[0,ULLONG_MAX]
有符号字符型 char/signed char
1 byte
[SCHAR_MIN, SCHAR_MAX]
无符号字符型 unsigned char
1 byte
[0, UCHAR_MAX]
宽字符型 wchar_t(__WCHAR_TYPE__)
2 byte/4 byte(__WCHAR_WIDTH__)
[WCHAR_MIN,WCHAR_MAX]
单精度浮点型float
4 byte(__SIZEOF_FLOAT__)
-3.4E-38~3.4E+38
双精度浮点型double
8 byte(__SIZEOF_DOUBLE__)
1.7E-308~1.7E+308
long double
8 byte(__SIZEOF_LONG_DOUBLE__)
说明:
(1)计算机存储的基本单位是1byte = 8bit,参考《字节串存储》。
(2)其中 bool 和 wchar_t 是 C++ 特有的。
对于条件判断,零为假,非零为真,对bool变量可赋非0非1的其他真值。
wchar_t 是一种整形的 typedef,用于表示宽字节字符集编码单元:typedef 为 short 容纳 UTF-16 编码单元,或 typedef 为 int 容纳 Unicode 编码单元。
在 macOS/Xcode/Clang 工具链中的 i386,x86_64,armv7(s),arm64 架构上,wchar_t 被定义为 int:
#define __WCHAR_TYPE__ int #define __WCHAR_WIDTH__ 32
(3)符号修饰符 signed 和 unsigned 用于修饰字符型和整形:默认为 signed 有符号,无符号需指定 unsigned。
例如 char 和 wchar_t 没有显式指定符号前缀,默认为有符号型,可定义宏 __CHAR_UNSIGNED__ 和 __WCHAR_UNSIGNED__ 将其指定为无符号型。
Xcode 工程配置 PROJECT TARGET | Build Settings | Apple LLVM 9.0 – Language 下有项 ‘char’ Type Is Unsigned: NO,也即 char 默认是带符号型(not unsigned)。如果要指定为无符号型,则可设置为YES,对应宏CHAR_UNSIGNED。
(4)长短修饰符 short 和 long 用于修饰整形:默认为 long 长整形,短整形需指定 short。
(5)当用 signed 和 unsigned、short 和 long 修饰 int 整形时,int 可省略。
(6)float 的精度(6位有效数字)通常是不够的,double 类型可以保证10位有效数字,能够满足大多数计算的需要。
使用 double 类型基本不会出错,在 float 类型中存在隐式的精度损失。默认的浮点字面值常量为 double 类型,在数值后面加上 F 或 f 表示单精度,例如 3.14159F。
浮点数 float、double 的存储设计,从本质上来说是设计了一个数值映射,充分利用了二进制存储的特点。参考IEEE754浮点数表示标准。
(7)void 的字面意思是“无类型”,不能用来定义变量。void 真正发挥的作用在于:
<1>对函数返回和函数参数的限定,例如自定义既不带参数也无返回值的函数 void MyFunc(void);
<2>定义无类型通用指针 void *,指向任何类型的数据。
(8)在Win32 API及MFC中为了使类型名称在语意上更明了,对以上基本类型进行了大量的 typedef。例如 WINDEF.H 中的 BYTE, WORD, DWORD。
(9)除上表以外,C/C++ 都可以自定义枚举 enum、联合 union 和 struct 结构体类型。
(10)标准C++库及STL还提供了通用数据结构:字符串类string;向量类模板vector;双端队列类模板deque;链表类模板list;容器适配器堆栈类stack(实现先进后出的操作);容器适配器队列类queue(实现先进先出的操作);集合类set;多重集合类multiset;映射类map;多重映射类multimap;位集合bitset;迭代器iterator (类似指针的功能,对容器的内容进行访问)。
CHAR_BIT / WORD_BIT / LONG_BIT
XcodeDefault.xctoolchain 的 usr/lib/clang/9.0.0/include/limits.h 中定义了 CHAR_BIT:
#define CHAR_BIT __CHAR_BIT__
CHAR_BIT 表示 char 类型的位宽(number of bits in achar),POSIX.1-2001 规范该值为 8。
sizeof 运算符可测量指定类型变量的字宽(以byte为单位的字节宽度),返回 size_t 类型;字宽乘以8 (CHAR_BIT) 得到位宽(以bit为单位的二进制位串宽度)。
—— BIT_WIDTH = sizeof(type)*CHAR_BIT
参考 gcc Common Predefined Macros 中 SIZEOF 和 WIDTH 宏(例如 __SIZEOF_POINTER__,__POINTER_WIDTH__ )。
Xcode 中 MacOSX.sdk 下的 usr/include/i386/limits.h 中定义了 WORD_BIT 和 LONG_BIT:
#if !defined(_ANSI_SOURCE) #ifdef __LP64__ #define LONG_BIT 64 #else /* !__LP64__ */ #define LONG_BIT 32 #endif /* __LP64__ */ #define SSIZE_MAX LONG_MAX /* max value for a ssize_t */ #define WORD_BIT 32
WORD_BIT 的值为 32,对应 int 类型的位宽(__SIZEOF_INT__*CHAR_BIT)。LONG_BIT 的值则随机器 CPU 字长。
_ILP32/__ILP32__,_LP64/__LP64__
GCC从 3.4 开始为所有的 LP64 平台定义了 `_LP64` 和 `__LP64__` 这两个宏,表示编译目标的 long int 和指针使用的是 64 位而 int 使用的是 32 位。
> These macros are defined, with value 1, if (and only if) the compilation is for a target where
long int
and pointer both use 64-bits andint
uses 32-bit.在 macOS 下可用 clang -dM 命令打印 Xcode 编译器在 各个 arch 指令集下的默认宏定义(macro definitions):
$ clang -dM -E -arch $arch -x c /dev/null
其中 $arch 可取 32 位的i386, 64 位的x86_64(amd64);32 位的 armv7(s),64 位的 arm64。
针对 32 位 CPU 定义了 _ILP32 和__ILP32__ 的值为1;针对 64位 CPU 定义了_LP64 和__LP64__ 的值为1。
Xcode 的 MacOSX.sdk 和 iPhoneOS.sdk 的 usr/include/stdint.h 进一步根据 __LP64__==1 定义了机器字长:
#if __LP64__ #define __WORDSIZE 64 #else #define __WORDSIZE 32 #endif
LONG_BIT (= __SIZEOF_LONG__ * CHAR_BIT)的值等于机器字长(__WORDSIZE),为 CPU GPRs(General-Purpose Registers,通用寄存器)的数据宽度:在32位CPU下为32,在64位CPU下为64。
Integers
char、short、int、long、long long 统称为整形。
某些类型数据的字宽(位宽)和数值范围由操作系统和编译平台决定,参考 Computing the Width of an Integer Data Type。
- char 为字节基元(1 byte),short 字宽 2 byte。
- 在古老的 16 位机上,sizeof(int) = 2,sizeof(long) = 4。
- 在主流 32 位/64 位机器上,int 字宽 4 byte(__SIZEOF_INT__),long long 字宽 8 byte(__SIZEOF_LONG_LONG__)。
- 32 位机上 sizeof(long) =__SIZEOF_LONG__ = 4;而 64 位机上 sizeof(long) = __SIZEOF_LONG__ = 8。
clang 编译器预定义宏 __SIZE_OF_type 指定了对应CPU架构下的类型字宽:
#define __SIZEOF_SHORT__ 2 #define __SIZEOF_INT__ 4
32位上 long (int) 是相对 short (int) 而言,字宽等于 int 为 4:
#define __SIZEOF_LONG__ 4 #define __SIZEOF_LONG_LONG__ 8
64位上的 long long 字宽和 long 一样都为 8:
#define __SIZEOF_LONG__ 8 #define __SIZEOF_LONG_LONG__ 8
XcodeDefault.xctoolchain 的 usr/lib/clang/9.0.0/include/limits.h 中对 clang 编译器预定义宏 MIN/MAX 进行了二次 define:
#define LONG_MAX __LONG_MAX__ #define LONG_MIN (-__LONG_MAX__ -1L) #define ULONG_MAX (__LONG_MAX__ *2UL+1UL) #if __STDC_VERSION__ >= 199901L || __cplusplus >= 201103L #undef LLONG_MIN #undef LLONG_MAX #undef ULLONG_MAX #define LLONG_MAX __LONG_LONG_MAX__ #define LLONG_MIN (-__LONG_LONG_MAX__-1LL) #define ULLONG_MAX (__LONG_LONG_MAX__*2ULL+1ULL) #endif
Xcode 中 MacOSX.sdk 下的 usr/include/i386/limits.h 中定义了 32 位和 64 位机器上的 (U)LONG、(U)LLONG 的值域(MIN,MAX)。
#ifdef __LP64__ #define ULONG_MAX 0xffffffffffffffffUL /* max unsigned long */ #define LONG_MAX 0x7fffffffffffffffL /* max signed long */ #define LONG_MIN (-0x7fffffffffffffffL-1) /* min signed long */ #else /* !__LP64__ */ #define ULONG_MAX 0xffffffffUL /* max unsigned long */ #define LONG_MAX 2147483647L /* max signed long */ #define LONG_MIN (-2147483647L-1) /* min signed long */ #endif /* __LP64__ */ #define ULLONG_MAX 0xffffffffffffffffULL /* max unsigned long long */ #define LLONG_MAX 0x7fffffffffffffffLL /* max signed long long */ #define LLONG_MIN (-0x7fffffffffffffffLL-1) /* min signed long long */
关于数据类型的位宽及值域可参考 MSDN 的 Data Type Ranges 和 GNU 的 Data Type Measurements & Layout of Source Language Data Types。
参考:
《difference between “short int” and “int”》《short int,int,long int 所占字节》
《CGfloat和float的区别?》《OS X以及iOS中与硬件环境相关的预定义宏》
__SIZEOF_POINTER__/__POINTER_WIDTH
clang 编译器预定义宏 __SIZEOF_POINTER__ 和 __POINTER_WIDTH 指定了相应 CPU 架构下指针的字宽和位宽。
32位机上的指针宽度为4byte:
#define __SIZEOF_POINTER__ 4 #define __POINTER_WIDTH__ 32
64位机上的指针宽度为 8 byte:
#define __SIZEOF_POINTER__ 8 #define __POINTER_WIDTH__ 64
uintptr_t & ptrdiff_t
C++11 在 <cstdint> 中提炼了容纳指针宽度的整形变量类型 intptr_t 和 uintptr_t 方便指针变量之间的计算。
Integer type capable of holding a value converted from a void pointer.
(u)intptr_t 是一种 typedefalias 类型,对应 clang 编译器预定义宏 __(U)INTPTR_TYPE__。
32位机上的 (u)intptr_t 的字宽为4byte(__SIZEOF_LONG__):
#define __INTPTR_TYPE__ long int #define __INTPTR_WIDTH__ 32 #define __UINTPTR_TYPE__ long unsigned int #define __UINTPTR_WIDTH__ 32
64位机上的 (u)intptr_t 的字宽为8byte(__SIZEOF_LONG__):
#define __INTPTR_TYPE__ long int #define __INTPTR_WIDTH__ 64 #define __UINTPTR_TYPE__ long unsigned int #define __UINTPTR_WIDTH__ 64
Xcode 的 MacOSX.sdk 和 iPhoneOS.sdk 的 usr/include/sys/_types/_intptr_t.h 中 typedef 了 intptr_t:
#ifndef _INTPTR_T #define _INTPTR_T #include <machine/types.h> /* __darwin_intptr_t */ typedef __darwin_intptr_t intptr_t; #endif /* _INTPTR_T */
在 MacOSX.sdk 的 usr/include/i386/_types.h 和 iPhoneOS.sdk 的 usr/include/arm/_types.h 中,__darwin_intptr_t 均被 typedef 为 long:
typedef long __darwin_intptr_t;
MacOSX.sdk 和 iPhoneOS.sdk 的 usr/include/sys/_types/_uintptr_t.h 中 uintptr_t 均被 typedef 为 unsigned long:
#ifndef _UINTPTR_T #define _UINTPTR_T typedef unsigned long uintptr_t; #endif /* _UINTPTR_T */
小结:
机器的指针位数和机器字长相等:
- sizeof(__INTPTR_TYPE__) = sizeof(__UINTPTR_TYPE__) = __SIZEOF_POINTER__ = __SIZEOF_LONG__
- __INTPTR_WIDTH__ = __UINTPTR_WIDTH__ = __POINTER_WIDTH__ = LONG_BIT = __WORDSIZE
ptrdiff_t 在 XcodeDefault.xctoolchain 的 usr/lib/clang/9.0.0/include/stddef.h 中被 typedef 为 clang 预定义编译宏 __PTRDIFF_TYPE__:
typedef __PTRDIFF_TYPE__ ptrdiff_t;
__PTRDIFF_TYPE__ 为 clang 编译器预定义宏,也是一种 typedef alias 类型。
32位机上的 ptrdiff_t 的字宽为4byte(__SIZEOF_LONG__):
#define __PTRDIFF_TYPE__ int #define __PTRDIFF_WIDTH__ 32 #define __SIZEOF_PTRDIFF_T__ 4
64位机上的 ptrdiff_t 的字宽为8byte(__SIZEOF_LONG__):
#define __PTRDIFF_TYPE__ long int #define __PTRDIFF_WIDTH__ 64 #define __SIZEOF_PTRDIFF_T__ 8
Xcode 中 MacOSX.sdk 和 iPhoneOS.sdk 的 include/sys/_types/_ptrdiff_t.h 定义了 ptrdiff_t
#ifndef _PTRDIFF_T #define _PTRDIFF_T #include <machine/types.h> /* __darwin_ptrdiff_t */ typedef __darwin_ptrdiff_t ptrdiff_t; #endif /* _PTRDIFF_T */
MacOSX.sdk/usr/include/i386/_types.h 和 iPhoneOS.sdk/usr/include/arm/_types.h 中定义了 __darwin_ptrdiff_t:
#if defined(__PTRDIFF_TYPE__) typedef __PTRDIFF_TYPE__ __darwin_ptrdiff_t; /* ptr1 - ptr2 */ #elif defined(__LP64__) typedef long __darwin_ptrdiff_t; /* ptr1 - ptr2 */ #else typedef int __darwin_ptrdiff_t; /* ptr1 - ptr2 */ #endif /* __GNUC__ */
<cstddef> 中定义的 ptrdiff_t 类型用于存储两个地址(uintptr_t)之间相差的偏移量(Result of pointer subtraction)。
C++ STL 容器迭代器偏移计算结果 difference_type 通常就是 ptrdiff_t(often synonymous with
std::ptrdiff_t
),参考《Import Data Types》。以下为 std::vector 的 Member Types 表格:
member type definition notes difference_type a signed integral type, identical to: iterator_traits<iterator>::difference_type usually the same as ptrdiff_t size_type an unsigned integral type that can represent any non-negative value of difference_type usually the same as size_t
参考:
《uintptr_t 类型》、《intptr_t、uintptr_t数据类型解析》和《使用intptr_t和uintptr_t》。
size_t
It is a type able to represent the size of any object in bytes: `size_t` is the type returned by the `sizeof` operator.
- std::size_t can store the maximum size of a theoretically possible object of any type (including array).
- std::size_t is commonly used for array indexing and loop counting.
C++ STL 容器一般都提供了 size 接口,返回存储元素的个数:
// Returns the number of elements in the container. size_type size() const;
顺序容器 array、vector 和 deque 还重载了 operator[] 运算符,支持像数组那样基于索引访问元素(引用):
// Returns a reference to the element at position n in the container. const_reference operator[] (size_type n) const;
以下为 std::vector 的 Member Types 表格:
member type definition notes difference_type a signed integral type, identical to: iterator_traits<iterator>::difference_type usually the same as ptrdiff_t size_type an unsigned integral type that can represent any non-negative value of difference_type usually the same as size_t 其中 size_type 通常就是 size_t(usually defined as a synonym for std::size_t),参考《Import Data Types》。
C++ STL <string>的 size() 接口和 [] 操作符则直接使用 size_t 参数:
// Returns the length of the string, in terms of bytes. size_t size() const; // Returns a reference to the character at position pos in the string. const char& operator[] (size_t pos) const;
<cstddef> 中定义的宏 offsetof (type,member) 返回成员变量在类型中的地址偏移量(return member offset),返回值通常是 size_t(ptrdiff_t?)。
size_t 在 XcodeDefault.xctoolchain 的 usr/lib/clang/9.0.0/include/stddef.h 中被 typedef 为 clang 预编译定义宏__SIZE_TYPE__:
typedef __SIZE_TYPE__ size_t;
32位机上的 __SIZE_TYPE__ 为 long unsigned int 类型,字宽为4byte(__SIZEOF_LONG__):
#define __SIZE_TYPE__ long unsigned int #define __SIZE_WIDTH__ 32 #define __SIZEOF_SIZE_T__ 4
64位机上的 __SIZE_TYPE__ 为 long unsigned int 类型,字宽为8byte(__SIZEOF_LONG__):
#define __SIZE_TYPE__ long unsigned int #define __SIZE_WIDTH__ 64 #define __SIZEOF_SIZE_T__ 8
一般来说,size_t 可能的最大值是 SIZE_MAX。
Xcode 中 MacOSX.sdk 和 iPhoneOS.sdk 的 usr/include/sys/_types/_size_t.h 定义了 size_t:
#ifndef _SIZE_T #define _SIZE_T #include <machine/_types.h> /* __darwin_size_t */ typedef __darwin_size_t size_t; #endif /* _SIZE_T */
MacOSX.sdk/usr/include/i386/_types.h 和 iPhoneOS.sdk/usr/include/arm/_types.h 中定义了 __darwin_size_t:
#if defined(__SIZE_TYPE__) typedef __SIZE_TYPE__ __darwin_size_t; /* sizeof() */ #else typedef unsigned long __darwin_size_t; /* sizeof() */ #endif
size_t 的取值与机器相关,某些情况下正确的使用 size_t 可以提高程序的可移植性和有效性。
参考:
《uintptr_t 类型》、《关于 size_t , uintptr_t , intptr_t, int》、《size_type、size_t、different_type以及ptrdiff_t》
认识size_t 和 为什么size_t重要?(Why size_t matters)。
size_t 的声明是实现相关的,它还出现在其他多个标准头文件中:<cstdio> <cstdlib> <cstring> <ctime> <cwchar>。
1. <cstdio> 中的以下函数接口参数用到了 size_t:
size_t fread ( void * ptr, size_t size, size_t count, FILE * stream ); size_t fwrite ( const void * ptr, size_t size, size_t count, FILE * stream ); // since C++11 int snprintf ( char * s, size_t n, const char * format, ... );
2. <cstdlib> 中的以下函数接口参数用到了 size_t:
void* calloc (size_t num, size_t size); void* malloc (size_t size); void* realloc (void* ptr, size_t size);
3. <cstring> 中的以下函数接口参数用到了 size_t:
const void * memchr ( const void * ptr, int value, size_t num ); int memcmp ( const void * ptr1, const void * ptr2, size_t num ); void * memcpy ( void * destination, const void * source, size_t num ); void * memmove ( void * destination, const void * source, size_t num ); void * memset ( void * ptr, int value, size_t num ); size_t strlen ( const char * str ); char * strncat ( char * destination, const char * source, size_t num ); int strncmp ( const char * str1, const char * str2, size_t num ); char * strncpy ( char * destination, const char * source, size_t num );
stdint
long从字面上看,应该是64位才更合理,把long当成32位实在是一个历史的包袱。像C#那样新起炉灶的程序语言,由于没有需要支持老代码的问题,就把long当作64位来处理了。
int 所占字宽(WORD_BIT)始终为 32 bits,当要求的数值范围为4byte时,建议使用int类型,因为第一版的C语言只有一种内置类型,那就是int。
在32位平台下,long是相对short而言,long(short)类型是long(short) int类型的简称,sizeof(int) = sizeof(long int) = 4。
在32位机器上,vc中__int64 以及 mac 中的struct wide/UnsignedWide为等价实现的64位长整形。
// MacTypes.h #if TYPE_LONGLONG #if defined(_MSC_VER) && !defined(__MWERKS__) && defined(_M_IX86) typedef signed __int64 SInt64; typedef unsigned __int64 UInt64; #else typedef signed long long SInt64; typedef unsigned long long UInt64; #endif #else typedef wide SInt64; typedef UnsignedWide UInt64; #endif /* TYPE_LONGLONG */
关于 _M_IX86 参考《编译器中和64位编程有关的预定义宏》。
MSDN 的 Data Type Ranges:
> C/C++ in Visual Studio also supports sized integer types. For more information, see__int8, __int16, __int32, __int64 andInteger Limits.MS-DTYPInteger Types:
> Microsoft C/C++ supports different sizes of integer types. An 8-bit, 16-bit, 32-bit, or 64-bit integer variable can be declared by using the __intn type specifier, where n is 8, 16, 32, or 64.
The types __int8, __int16, and __int32 are synonyms for the ANSI/ISO C types (as specified in [ISO/IEC-9899]) that have the same size. They are useful for writingportable code that behaves identicallyacross multiple platforms.
int和long的范围虽然一样,但输入输出格式不同,printf int 的格式为%d,而 printf long (int) 的格式为%ld,print long long (int) 的格式则为%lld。
考虑到程序的可移植性,还是要将它们区分开来。C99 标准中 <inttypes.h> 以及 C++11 的 <stdint.h> 中定义了适配各平台指定位宽的整形类型:
- int8_t/uint8_t;
- int16_t/uint16_t;
- int32_t/uint32_t;
- int64_t/uint64_t;
- intptr_t/uintptr_t;
字面值整数常量的类型默认为int或long,其精度类型取决于精度值,其值适合int型就是int型,比int型(INT_MAX)大的就是long类型。通过增加后缀可强制将字面值整数常量转换成long、unsigned或unsigned long类型。通过在数值后面添加L或l(推荐使用L,防l与1混淆)指定常量为long类型。例如128u,1L,1024UL,8Lu。没有short类型的字面值常量。
demo
以下代码片段打印机器字宽(SIZE)、位宽(WIDTH,*_BIT)以及取值范围(MIN,MAX)。
#include <iostream> #include <cstdint> // C++11 #include <climits> #if __WORDSIZE==32 #pragma message("__WORDSIZE==32") #elif __WORDSIZE==64 #pragma message("__WORDSIZE==64") #endif // 获取指针宽度(机器字宽) int GetWordSize() { return sizeof(uintptr_t)*CHAR_BIT; } int main(int argc, const char * argv[]) { std::cout << "WordSize = " << GetWordSize() << std::endl; // 64 std::cout << "__WORDSIZE = " << __WORDSIZE << std::endl; std::cout << std::endl; std::cout << "========== LONG_BIT ==========" << std::endl; std::cout << "CHAR_BIT = " << CHAR_BIT << std::endl; // 8 std::cout << "WORD_BIT = " << WORD_BIT << std::endl; // 32 std::cout << "LONG_BIT = " << LONG_BIT << std::endl; // 32 for 32 bit; 64 for 64 bit std::cout << std::endl; std::cout << "========== __SIZEOF_INT__ ==========" << std::endl; std::cout << "__SIZEOF_SHORT__ = " << __SIZEOF_SHORT__ << std::endl; std::cout << "__SIZEOF_INT__ = " << __SIZEOF_INT__ << std::endl; std::cout << "__SIZEOF_LONG__ = " << __SIZEOF_LONG__ << std::endl; std::cout << "__SIZEOF_LONG_LONG__ = " << __SIZEOF_LONG_LONG__ << std::endl; std::cout << std::endl; std::cout << "========== __SIZE_TYPE__ ==========" << std::endl; std::cout << "sizeof(size_t) = " << sizeof(size_t) << std::endl; std::cout << "__SIZEOF_SIZE_T__ = " << __SIZEOF_SIZE_T__ << std::endl; std::cout << "__SIZE_WIDTH__ = " << __SIZE_WIDTH__ << std::endl; std::cout << std::endl; std::cout << "========== POINTER, UINTPTR, PTRDIFF ==========" << std::endl; std::cout << "__SIZEOF_POINTER__ = " << __SIZEOF_POINTER__ << std::endl; std::cout << "__POINTER_WIDTH__ = " << __POINTER_WIDTH__ << std::endl; std::cout << "sizeof(uintptr_t) = " << sizeof(uintptr_t) << std::endl; std::cout << "__INTPTR_WIDTH__ = " << __INTPTR_WIDTH__ << std::endl; std::cout << "__UINTPTR_WIDTH__ = " << __UINTPTR_WIDTH__ << std::endl; std::cout << "sizeof(ptrdiff_t) = " << sizeof(ptrdiff_t) << std::endl; std::cout << "__SIZEOF_PTRDIFF_T__ = " << __SIZEOF_PTRDIFF_T__ << std::endl; std::cout << "__PTRDIFF_WIDTH__ = " << __PTRDIFF_WIDTH__ << std::endl; std::cout << std::endl; std::cout << "========== __WCHAR_TYPE__ ==========" << std::endl; std::cout << "sizeof(wchar_t) = " << sizeof(wchar_t) << std::endl; std::cout << "__WCHAR_WIDTH__ = " << __WCHAR_WIDTH__ << std::endl; std::cout << std::endl; std::cout << "========== *_MAX ==========" << std::endl; // 1byte std::cout << "SCHAR range = [" << SCHAR_MIN << "," << SCHAR_MAX << "]" << std::endl; std::cout << "UCHAR range = [" << "0" << "," << UCHAR_MAX << "]" << std::endl; // 2byte std::cout << "SHRT range = [" << SHRT_MIN << "," << SHRT_MAX << "]" << std::endl; std::cout << "USHRT range = [" << "0" << "," << USHRT_MAX << "]" << std::endl; // 4byte std::cout << "INT range = [" << INT_MIN << "," << INT_MAX << "]" << std::endl; std::cout << "UINT range = [" << "0" << "," << UINT_MAX << "]" << std::endl; // 4byte for 32bit; 8byte for 64bit std::cout << "LONG range = [" << LONG_MIN << "," << LONG_MAX << "]" << std::endl; std::cout << "ULONG range = [" << "0" << "," << ULONG_MAX << "]" << std::endl; // 8byte std::cout << "LLONG range = [" << LLONG_MIN << "," << LLONG_MAX << "]" << std::endl; std::cout << "ULLONG range = [" << "0" << "," << ULLONG_MAX << "]" << std::endl; std::cout << std::endl; return EXIT_SUCCESS; }
参考:
《程序设计与C语言》 梁力
《白话C++》 南郁
《Visual C++面向对象编程教程》 王育坚
《C++ Primer》Stanley B. Lippman
《程序员的自我修养》《操作系统位数》《查看操作系统位数》
《32位还是64位》《kernel里的long和int》
《浮点数存储格式》《浮点数在内存中的存储格式》
《Windows/MFC数据类型》
《针对C/C++开发人员采用Windows 64位》
MS-DTYP:Windows Data Types / Windows Runtime base data types