【C/C++】size_t详解

小白yaa 2024-07-24 13:05:02 阅读 58

<code>size_t 是一种无符号整数类型,通常用于表示对象的大小或数组的索引。它在C和C++标准库中经常用于与内存分配、数组索引和计算对象大小等相关的操作。size_t 类型的变量通常用于存储非负整数值。

size_t 的大小(即占用多少字节)是平台相关的,它可以根据编译器和操作系统的不同而变化。通常情况下,size_t 被设计成足够大,可以容纳你的系统上最大可能的对象大小。

在C++中,size_t 类型通常用于循环计数器、数组索引、内存分配函数(例如 malloccalloc 返回的大小)以及与标准容器(如 std::vectorstd::string)一起使用时的大小和容量等。

使用size_t可能会提高代码的可移植性、有效性或者可读性,或许同时提高这三者。

在标准C/C++的语法中,只有int、float、char、bool等基本的数据类型,至于 size_t 或 size_type 都是以后的编程人员为了方便记忆所定义的一些便于理解的由基本数据类型的变体类型。

总之,size_t 是C++中表示大小和索引的标准类型,通常用于与内存和数据结构相关的操作。

一、实现

        

size_t是标准C库中定义的,它是一个基本的与机器相关的无符号整数的C/C + +类型, 它是sizeof操作符返回的结果类型,该类型的大小可选择。其大小足以保证存储内存中对象的大小(简单理解为 unsigned int就可以了,64位系统中为 long unsigned int)。通常用sizeof(XX)操作,这个操作所得到的结果就是size_t类型。

类似的还有wchar_t, ptrdiff_t。

wchar_t就是wide char type,“一种用来记录一个宽字符的数据类型”。ptrdiff_t就是pointer difference type,“一种用来记录两个指针之间的距离的数据类型”。

通常,size_t和ptrdiff_t都是用typedef来实现的,如下你可能在某个头文件里找到类似的语句。而wchar_t在一些旧的编译器中可能是用typedef来实现,但是新的标准中wchar_t已经是C/C++语言的关键字,其地位与char、int等同。

typedef unsigned int size_t;

主要特点和用途:

无符号整数类型: size_t 是无符号整数类型,意味着它只能表示非负整数,包括0。它不存储负数值。

平台相关性: size_t 的大小在不同的编译器和平台下可以不同。通常情况下,它被定义为足够大以容纳目标平台上最大对象的大小。例如,在大多数32位系统上,size_t 是4字节(32位),而在64位系统上通常是8字节(64位)。

用于数组索引: size_t 常用于循环中,特别是用于遍历数组或容器的元素。它可以保证足够大以表示数组的索引范围,从而避免溢出问题。

用于内存分配: size_t 通常用于表示内存分配的大小,例如 newmalloc 函数的参数。这有助于确保分配足够的内存以容纳数据。

标准库中的使用: C++标准库中的许多函数和容器(如std::vectorstd::string等)使用size_t 来表示容器的大小、元素数量等。

示例用法:

#include <iostream>

#include <vector>

int main() {

std::vector<int> numbers = {1, 2, 3, 4, 5};

// 使用 size_t 来遍历容器

for (size_t i = 0; i < numbers.size(); ++i) {

std::cout << numbers[i] << " ";

}

std::cout << std::endl;

return 0;

}

二、为什么需要size_t

在标准C库中的许多函数使用的参数或者返回值都是表示的用字节表示的对象大小,比如malloc(n) 函数的参数n指明了需要申请的空间大小、memcpy(s1, s2, n)的最后一个参数表明需要复制的内存大小、strlen(s)函数的返回值表明了以’\0’结尾的字符串的长度(不包括’\0’)。

或许你会认为这些参数或者返回值应该被申明为int类型(或者long或者unsigned),但是事实上并不是。C标准中将他们定义为size_t。标准中记载malloc、memcpy和strlen的声明:

//malloc()

void *malloc(size_t n);

//memcpy()

void *memcpy(void *s1, void const *s2, size_t n);

//strlen()

size_t strlen(char const *s);

 

size_t还经常出现在C++标准库中,此外C++库中经常会使用一个相似的类型size_type。

size_t是全局定义的类型;size_type是STL类中定义的类型属性,用以保存任意string和vector类对象的长度string::size_type 制类型一般就是unsigned int, 但是不同机器环境长度可能不同 win32 和win64上长度差别;size_type一般也是unsigned int

 

 三、可移植性问题

早期的C语言并没有提供size_t类型,C标准委员会为了解决移植性问题将size_t引入,从而让程序有良好的可移植性。举例如下:

对于一个可移植的标准memcpy(s1, s2, n)函数,其将s2指向地址开始的n个字节拷贝到s1指向的地址并返回s1。这个函数可以拷贝任何数据类型,所以参数和返回值类型应为void*。而源地址不应被改变,所以第二个参数s2类型应该为const void*。

问题在于我们如何声明个参数,它代表了源对象的大小:

 

void *memcpy(void *s1, void const *s2, int n);

3.1、使用int

使用int类型在大部分情况下都是可以的,但是并不是所有情况下都可以。int是有符号的,它可以表示负数,但是大小不可能是复数。

3.2、使用unsigned int

使用unsigned int代替它让第三个参数表示的范围更大,大部分机器上其最大值是int最大值的两倍。尽管如此,但在给定平台上 int 和 unsigned int 对象的大小是一样的。因此使用unsigned int修饰第三个参数的代价与int是相同的:

void *memcpy(void *s1, void const *s2, unsigned int n);

3.3、使用unsigned long int

unsigned int可以表示最大类型的对象大小只有在整形和指针类型具有相同大小的情况下,比如说在IP16中,整形和指针都占2个字节16位;而在IP32上面,整形和指针都占4个字节32位。

但在I16LP32架构上(整形是16位,长整形和指针类型时32位)则不够用了,比如摩托罗拉第一代处理器68000,处理器可能拷贝的数据大于65535个字节,但是这个函数第三个参数n不能处理这么大的数据。

 

void *memcpy(void *s1, void const *s2, unsigned long n);

3.4、问题

但是在IP16平台上相比于使用unsigned int,你使用unsigned long可能会使你的代码运行效率大打折扣(代码量变大而且运行变慢)。在标准C中规定长整形(无论无符号或者有符号)至少占用32位,因此在IP16平台上支持标准C的话,那么它一定是IP16L32 平台。这些平台通常使用一对16位的字来实现32位的长整形。在这种情况下,移动一个长整形需要两条机器指令,每条移动一个16位的块。事实上,这个平台上的大部分的32位操作都需要至上两条指令。

因此,以可移植性为名将memcpy的第三个参数申明为unsigned long而降低某些平台的性能是我们所不希望看到的。使用size_t可以有效避免这种情况。

size_t类型是一个类型定义,通常将一些无符号的整形定义为size_t,在使用 size_t 类型时,编译器会根据不同系统来替换标准类型。每一个标准C实现应该选择足够大的无符号整形来代表该平台上最大可能出现的对象大小。在使用 size_t 类型时,编译器会根据不同系统来替换标准类型。

四、size_t 与 sizeof()

4.1、sizeof的作用

sizeof是c的运算符之一,用于获取操作数被分配的内存空间,以字节单位表示。

其操作数可以是变量,也可以是数据类型如int,、loat等。所以可以通过它来获取本地c库定义的基本类型的范围。

4.2、sizeof的使用

对于一般变量,形式2种:sizeof a 或 sizeof(a);对于数据类型,必须使用带括号的方式,如sizeof(int).

4.3、sizeof和size_t

常常会有人认为 在C/C++中 sizeof 是一个函数,而实际上C/C++中的sizeof 是一个运算符。sizeof 运算符的结果是 size_t ,它是由 typedef 机制定义出来的”新”类型。

C/C++用 typedef 把 size_t 作为 unsigned int或 unsigned long 的别名,可以简单的理解为size_t 有如下两种定义

 

typedef unsigned int size_t

thpedef unsigned long size_t12

//可以用%zd(C99标准新增)、%u、%lu 转换说明用于 printf() 显示 size_t 类型的值

#include "stdio.h"

int main(void)

{

size_t intsize = sizeof (int);

printf("%zd\n", sizeof (int));

printf("%zd\n", intsize);

printf("%u\n", intsize);

printf("%lu\n", intsize);

return 0;

}

//输出结果为:

//4

//4

//4

//4



声明

本文内容仅代表作者观点,或转载于其他网站,本站不以此文作为商业用途
如有涉及侵权,请联系本站进行删除
转载本站原创文章,请注明来源及作者。