### C语言关键字浅析系列 ###
### ISO/ANSI C 关键字 ###
sizeof,本意为size of sth.,指某个事物的尺寸/长度
在C语言中,sizeof的用法与其名字也基本吻合,而且不同于其他常见的用于类型声明的或者作为限定词的关键字
类似于++和--,sizeof关键字是C语言的一个单目运算符
也就是说在某些计算上我们才会用到sizeof关键字
sizeof的作用是:
作为单目运算符,以字节形式给出其操作数的存储大小。
1、sizeof的格式和优先级
sizeof与操作数的格式一般要根据操作数的类型而定:
char ch;
sizeof(char); /* 数据类型作为操作数必须加小括号 */
sizeof(ch); /* 变量作为操作数,以下两种形式均可,即可以省略小括号 */
sizeof ch; /* 但习惯上还是会都加上小括号,该行这种写法很少见,不过也是正确的 */
sizeof的对象是有限制的,不是所有的C语言的东西都能拿来sizeof一下,比如以下这些东西就不能拿来sizeof:
bool max(){return true;} /* 定义一个函数 */
sizeof(max); /* 非法操作,不能对函数sizeof */
int M; /* M未知 */
float f[M]; /* 数组f长度未知 */
sizeof(f); /* 这是一种不完全类型,即未知存储大小的数据类型,不完全类型不能被sizeof */
sizeof(void); /* 不完全类型,不能被sizeof。其他常见不完全类型还有:未知内容的结构或联合 */
/* 不能被sizeof的有:函数类型、不完全类型、位字段 */
既然sizeof是C的一个单目运算符,其必有自己的优先级,通常sizeof为2级优先级,与常见的几个单目运算符都是一级
比如* & ! ~ ++ --,2级比3级的高,3级的有/(除)、 %(求模)、 *(乘)
2、sizeof的结果
sizeof形式上看神似一个函数,但它并不是函数,不过它的运算结果需要一个称之为size_t的类型来存储
从其在头文件中的定义我们能看出它的本质:typedef unsigned int size_t;
所以其实我们能得到的结果是一个整数,意指字节形式表示的操作数的存储大小
在ISO/ANSI C标准中有这样的规定,规定char类型为1个字节长度,故以下类型的sizeof结果都是1:
sizeof(char); /* 字符类型 */
sizeof(unsigned char); /* 无符号字符类型 */
sizeof(signed char); /* 有符号字符类型 */
字符类型是在标准中规定过的,所以一般各种机器平台里面的C的字符类型都是1,但其他类型由于标准中未规定,所以长度不一定统一
以目前的趋势——64位的系统为例:
/* 以下只是某个机器上的类型长度,具体数据根据系统和机器而定 */
sizeof(int) = 4; sizeof(unsigned int) = 4; sizeof(short) = 2; sizeof(unsigned short) = 2;
sizeof(long int) = 4; sizeof(unsigned long) = 4; sizeof(long long) = 8;
sizeof(float) = 4; sizeof(double) = 8; sizeof(long double) = 8;
/*
指针类型比较特殊,其大小是依赖于编译器的,在Microsoft C/C++ 7.0中,near类指针是2byte,far和huge类指针是4byte
在UNIX/Linux系统中指针通常为4byte,如下面这条伪代码
*/
char *p;
sizeof(p) = 4;
对确定的数组sizeof,得到的结果是数组的总大小,即等于数组长度乘以元素的存储大小:
char a[10];
sizeof(a) = 10; /* char的长度是1byte,数组长度为10,结果为1*10=10 */
int b[10];
sizeof(b) = 40; /* int的长度为4byte,数组长度为10,结果为4*10=40 */
对常量形式的操作数,会先按照常量的形式转化到相应类型,再sizeof:
sizeof(3) = 4; /* 整数常量,默认是int */
sizeof(3.14) = 8; /* 浮点常量,默认是double */
sizeof("abcd"); /* 字符串常量,其类型根据系统而定,可能会是数组类型或者指针类型 */
对于结构和联合,其sizeof的计算方式类似,但又有区别:
union u
{
char a; /* sizeof(char) = 1 */
int b; /* sizeof(int) = 4 */
double c; /* sizeof(double) = 8 */
};
sizeof(u) = 8; /* 对于联合,sizeof是计算联合的成员中存储空间最大的,此联合中double最大,故sizeof得到8 */
struct s
{
char a; /* sizeof(char) = 1 */
int b; /* sizeof(int) = 4 */
double c; /* sizeof(double) = 8 */
};
sizeof(s) = 13; /* 对于结构,sizeof是计算所有成员的存储空间之和,即1+4+8=13,注意Linux中的C可能不是这个计算方式 */
/* 注意:对以上这种结构体进行sizeof运算,得到的结果可能不是13,而是16,这是因为有的系统自动优化将结构体的成员进行了对齐,比如使得char变量占用了4byte内存 */
3、sizeof的用途
相比类似的++和--,sizeof也许在初学C的时候几乎很少用,但这不妨碍它在其他地方发挥其用武之地
比如常见的计算数组中元素个数的函数:
void * memset(void * s, int c, sizeof(s));
再就是与存储分配和I/O系统那样的例程进行通信:
void *malloc(size_t size);
sizeof_t fread(void* ptr , size_t size , size_t nmemb , FILE* stream);
——参考《C Primer Plus第五版》