size_t——为什么支持size_t,何时使用size_t?

为什么会有 ”size_t为何要存在” 的疑问?

许多C/C++文件中都会出现类型size_t,比如在bitcoin源码中,有这样的一个函数:

size_t strnlen( const char *start, size_t max_len)
{
    const char *end = (const char *)memchr(start, '\0', max_len);
    //memchr函数从start开始寻找第一个出现字符'\0'的位置并返回
    return end ? (size_t)(end - start) : max_len;
    //const char的长度吧,为啥要这样写,为什么要单独写一个文件啊,NOTE
}

该函数完成了返回const char*类型start代表的串的长度,返回值被设置为size_t类型。这是size_t经常被使用的一个场景“数组可能的长度

另一个使用场景就是函数memcpy(其实本质上是一样的,都是表示内存中数据的多少)。memcpy的原型void* memcpy(void*to,const void*from,size_t n)。需要复制的字节数被设置为size_t类型,这是数据块的大小

于是,会给人一种感觉,这种工作int也可以完成,如果说需要排除负数,unsigned int也可以完成。为什么要多此一举引入size_t呢?

另外,为何要表示内存中所有的数据呢?为什么不是硬盘?
这就是操作系统范畴的东西了。程序所使用的数据,一定是先由OS把数据搬/swap到内存,再根据内存地址去访问。至于怎么从硬盘中找到,就是另一件事情了,它被叫做”缺页中断“。

为什么需要size_t?

首先声明size_t的功能,它需要保证在程序运行中可以表示所有内存地址。size_t根据具体机器的体系结构,将有不同的值。比如,32位系统,内存最大是$2^{32} bytes=4G$。那么size_t就需要至少4个字节(32bits)来表示所有地址。

即使是这样,unsigned int不是也是4个字节吗?
有些系统是。

为了保证在一些有者特殊体系结构的机器上正确运行,使用unsigned int来表示数据块大小可能是一个不好的主意。比如,一个机器支持16bit的unsigned int,但他是一个32位系统,使用unsigned int代替size_t显然并不是一个好主意。假如出现一个特别大的数组,可能无法表示出这个数组所有的元素,显而易见。
那么,是否可以使用unsigned long来代替呢?毕竟,long一定需要至少32bits,那么,对于那些只有16位的平台呢,这些平台往往使用两个16bits的字来对应一个long,在对long进行操作时,一定需要至少两条操作指令。而在这个系统中,并不需要32bits的地址,因为他只有16位。
要为了兼容而舍弃性能吗?显然有更好的解决方案。那就是根据地址总线个数来决定一个类型的大小,既不会无法表示一些数据,又不会使一些机器效率折损。这个类型就是size_t
size_t的存在使得程序有更好的可移植性,显而易见,程序员不需要为了一个新机器而在unsigned intunsigned char等等类型之间改来改去。

size_t的使用

正如上述,size_t可以表示内存中的所有数据,因为它刚好能够表示内存中所有的地址。
根据定义,size_t是关键字sizeof运算得到的结果的类型。因此,使用sizeof得到的结果应该声明为size_t

size_t n=sizeof(int)

另外,就是第一小节所述的,表示数组大小、数据块大小等等(实际上也是数据块的大小)。

使用size_t的时候,记得包括它的定义所在头文件,比如<stddef.h>, <stdio.h>, <stdlib.h>, <string.h>, <time.h>,<wchar.h>中的任意一个。

Reference

为什么size_t重要?
size_t类型

猜你喜欢

转载自www.cnblogs.com/riko707/p/11437328.html
今日推荐