size_t数据类型的意义
1 int
的各种类型和size_t
类型
计算机内存由一些叫做位(bit)的单元组成,int
相关的类型(short
, int
,long
, long long
)通过使用不同数目的位来存储值。如果在所有的系统中,每种类型的宽度(这里的宽度描述存储整数时使用的内存量,使用的内存越多,则越宽)都相同,则使用起来会非常方便,例如,short
总是16位,int
总是32位等等,但是生活并非那么简单,没有一种选择能够满足计算机设计的要求。C++
提供了一种灵活的标准,它确保了最小长度,比如:
short
至少16位int
至少与short
一样长long
至少32位,且至少与int
一样长long long
至少64位,且至少与long
一样长
当前很多操作系统都使用了最小长度,这位int提供了多种选择,其宽度可以是16位,24位或32位,同时又符合标准,甚至可以是64位。在老式的IBM PC的实现中,int的宽度为16位(与short相同),而在Windows XP,Windows Vista,Windows 7,Macintosh OS X,VAX和很多其他微型计算机实现中,为32位。类型的宽度随实现而异,这可能在将C++程序从一种环境移到另一种环境(包括在同一个系统中使用不同编译器)时引发问题。
比如,如果知道变量可能表示的整数值大于16位整数的最大可能值,如果使用int类型,在32位系统上是可以正常工作的,但是程序移植到16位系统上就无法正常工作,因为超越限制了。
size_t
的诞生是为了让程序具有可移植性,size_t
是一些C/C++
标准在stddef.h
中定义的,它的真实类型与操作系统有关。
//在32位操作系统中被普遍定义为:
typedef unsigned int size_t; //4个字节
//在64位操作系统中被定义为:
typedef unsigned long size_t; //8个字节
而int
在不同的操作系统上都是4个字节,与size_t
不同,且int
是带符号的,size_t
是无符号的。
2 size_t类型的意义
size_t
类型是无符号的,但size_t
和unsigned int
又有所不同,size_t
的取值范围是目标平台下最大可能的数组尺寸,一些平台下的size_t
范围小于int
的正数范围,又或者大于unsigned int
。比如在64位下,int
是4个字节,但是size_t
是8个字节,这就意味着在64位下最大可能开辟的数组尺寸是2^64,如果使用int
作为数组的尺寸标记,那么就会失去 2^ 32 尺寸的数组机会。但是你会说谁会在64位系统上开辟一个大于2^32大小的连续数组呢?不不不,size_t
数据类型的意义并不在于此。
举个例子:在标准的C库中的许多函数使用的参数或者返回值都是表示的用字节表示的对象大小,如下:
// 按字节拷贝,从s2拷贝n个字节到s1地址
void *memcpy( void *s1 , const void *s2 , size_t n)
第三个参数数据类型如果改成int
可以吗?在大部分情况下是可以的,但并不是所有情况都可以。
int
是有符号的,它可以表示负数,但是大小只能是大于等于0,所以我们用unsigned int
类型来代替int
类型,会让第三个参数表示的范围更大。在大部分机器上,unsigned int
类型的最大值是int
类型的最大值的两倍,比如,在16位机器上,unsigned int
的最大值为65535,int
的最大值为32767。
void *memcpy( void *s1 , const void *s2 , unsigned int n)
若第三个参数采用unsigned int
类型,在16-bit 长整形
和指针类型32-bits
的平台上就不够用了,比如说摩托罗拉第一代处理器68000,在这种情况下,处理器可能拷贝的数据大于65535个字节,但是这个函数第三个参数n
不能处理这么大的数据。
若第三个参数采用unsigned long
类型呢?
void *memcpy(void *s1, void const *s2, unsigned long n);
显然,该类型可以处理更大的数据,移植性要比unsigned int
类型好很多,但是性能呢?比如在16位平台上,相较于unsigned int
类型来说,使用unsigned long
类型会使你的代码运行效率大打折扣(因为代码量变大导致运行变慢)。
使用size_t可以有效避免这种情况。size_t类型是一个类型定义,通常将一些无符号的整形定义为size_t,比如说nsigned int
或者unsigned long
,甚至unsigned long long
。
每一个标准C实现应该选择足够大的无符号整形来代表该平台上最大可能出现的对象大小,因此使用size_t
来代替int
或unsigned
可以保证在同一个平台中,始终得到一个数据类型或变量的字节大小,保证了程序对该数据类型或变量的统计方式始终一致,不会因为平台的改变而出现错误。
3 总结
-
使用size_t可能会提高代码的可移植性(不会因为平台的改变出现错误,因此对于无符号的整型数据,尽可能使用 size_t,而不是 int 或 unsigned)
-
使用size_t可能会提高代码的可读性(看到一个变量申请为size_t类型,你就知道它代表字节大小或数组索引,而不是错误代码或者使一个普通的值)
-
使用size_t可能会提高代码的程序效率(在16位系统上申请
unsigned long
数据类型需要两条机器指令去执行,大大降低了效率)