
3.8.1 sizeof()运算符
sizeof()运算是C语言内置的函数,我们把某种数据类型传给它作参数,就可以得到该类型占据的字节数。下面就写一个程序,看看这个运算符如何使用。
在程序的第一部分,我们通过#include指令把必要的头文件包含进来,然后声明函数原型,并创建main()函数。虽然笔者把整个程序分成两部分展示,但这两个部分实际上是写在同一个文件(也就是sizes_ranges1.c文件)里的。下面就是该程序第一部分的代码:

这段程序先引入stdio.h这个头文件,然后引入了两个我们以前没有见过的头文件,也就是stdint.h与stdbool.h。第一个头文件stdio.h包含许多内容,其中有我们要用的一个函数,也就是printf()函数的原型。第二个头文件stdint.h声明了每一种固有数据类型的字节数。第三个头文件stdbool.h定义了bool这个数据类型,以及true与false这两个bool值。这三个头文件都是C语言标准库(C Standard Library)的一部分。我们后面还会用到C语言标准库里的许多头文件,但并不会把每个文件都用一遍。本书附录G会列出C语言标准库里的各种文件,并简单地介绍每个文件。我们在第24章会详细讲解头文件。
大家都看到了,main()函数会调用printSizes()函数,这个函数我们已经声明过了(或者说,我们已经把它的原型给声明出来了),但还没有为它编写完整的定义。于是,我们在该程序的第二部分定义这个函数:

这个程序必须包含<stdint.h>头文件,因为该程序提到了一些宽度固定的整数类型,而这些类型是由这份头文件来定义的。如果不引入,那么编译时就会出错。大家试着把引入头文件的这行include指令注释掉,然后编译程序,看看会有什么结果。
程序还提到了C语言后来定义的bool类型,因此也必须把定义该类型的<stdbool.h>文件包含进来。大家试试看,如果不引入这份文件,编译时会有什么问题。
在笔者的系统上,sizeof()的返回类型是unsigned long,因此,为了让printf()函数正确地打印出这样的返回值,我们应该使用%lu这个格式说明符来描述该值[1]。
该程序在笔者的系统上运行会产生这样的输出信息。


笔者使用的是64位操作系统,它用8个字节(也就是64个二进制位)来表示指向某个内存地址的指针,因此,long与unsigned long类型也是用8个字节来实现的。
大家在自己的操作系统上运行这个程序,看看结果跟这里有什么区别。
[1] 在Linux操作系统上,可以通过echo | gcc -E -xc -include 'stddef.h'-| grep size_t命令查询sizeof()的实际返回类型。另外,也可以改用%zu作说明符,这样就不用关注sizeof()的实际返回类型了。——译者注