C

C 学习笔记 - 理解 size_t

C Learning Notes - Understanding size_t

Posted by zihengCat on 2017-06-02

前言

本文讲解 C 语言中 size_t 类型及其应用。

size_t 类型

在 C 语言的标准头文件中与很多内核项目中,都能发现 size_t 这个”数据类型”的身影,如函数参数、函数返回值、循环控制变量…似乎size_t无处不在,可是我们又不太了解这个”数据类型”。

实际上,size_t是个无符号整型,它并不是一个全新的数据类型,更不是一个关键字。size_t是由typedef定义而来的,我们在很多标准库头文件中都能发现。

C 标准头文件<stddef.h>中可以找到size_t的实际定义。

...
#define __SIZE_TYPE__ long unsigned int
typedef __SIZE_TYPE__ size_t;
...

代码清单:<stddef.h> 中的 size_t

在我个人的机器上,size_t的真面目即:long unsigned int

使用 size_t 的缘由

查阅相关文档后了解到,size_t的含义是size type,是一种计数类型。取值范围与机器架构与操作系统相关。32 位机器一般是unsigned int,占 4 字节;而 64 位机器一般是unsigned long,占 8 字节。

size_t类型常被用作计数用途,例如:sizeof运算符得到对象所占的字节数;字符串函数strlen返回字符串的长度等等,其返回值都为size_t类型。

size_t类型隐含着本机理论所能容纳建立最大对象的字节数大小的含义,因此常被用于数组索引、内存管理函数中。

最初设计size_t类型初衷,是为了程序的跨平台兼容性考虑。

size_t 小陷阱

在 Google 搜索的时候,还发现了一个非常有趣的案例。

#include <stdio.h>
#include <string.h>

int main(void) {
    int i = -1;
    if (i < strlen("hello")) {
        printf("Hello, World\n");
    } else {
        printf("Hello, ziheng\n");
    }
    return 0;
}

代码清单:size_t 陷阱

$ gcc test.c && ./a.out
Hello, ziheng

代码清单:size_t 程序执行结果

上述代码编译执行后,程序打印出了else分支语句Hello, ziheng,这似乎与预想的有些不同。

实际上,这段代码的if条件比较中触发了 C 语言隐式自动类型转换机制,size_t实际类型为unsigned long int,而带符号整型变量isize_t比较时会被类型提升自动转换为无符号整型unsigned int,数值-1转化无符号整型数是4294967295,远大于字符串长度5

带符号数和无符号数之间的运算操作,请一定小心。

参考资料