• 欢迎访问开心洋葱网站,在线教程,推荐使用最新版火狐浏览器和Chrome浏览器访问本网站,欢迎加入开心洋葱 QQ群
  • 为方便开心洋葱网用户,开心洋葱官网已经开启复制功能!
  • 欢迎访问开心洋葱网站,手机也能访问哦~欢迎加入开心洋葱多维思维学习平台 QQ群
  • 如果您觉得本站非常有看点,那么赶紧使用Ctrl+D 收藏开心洋葱吧~~~~~~~~~~~~~!
  • 由于近期流量激增,小站的ECS没能经的起亲们的访问,本站依然没有盈利,如果各位看如果觉着文字不错,还请看官给小站打个赏~~~~~~~~~~~~~!

C++ Variable Types

C/C++基础 弦苦 3043次浏览 0个评论

在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 工具链中的 i386x86_64armv7(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 and int 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。

__WORDSIZE

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.

  1. std::size_t can store the maximum size of a theoretically possible object of any type (including array).  
  2. 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-DTYPWindows Data Types / Windows Runtime base data types  


开心洋葱 , 版权所有丨如未注明 , 均为原创丨未经授权请勿修改 , 转载请注明C++ Variable Types
喜欢 (0)

您必须 登录 才能发表评论!

加载中……