C/C++中的sizeof

来源:互联网 发布:数控车床软件编程 编辑:程序博客网 时间:2024/06/16 00:41

在介绍sizeof之前,先明确一点:sizeof是操作符,不是函数!

对sizeof的学习与理解主要参考MSDN上的介绍,也参考了一些其他博客或论坛中的解说。

1、sizeof的介绍:

sizeof的语法是

sizeof unary-expression sizeof ( type-name )

MSDN中说sizeof运算符的结果是size_t类型,是包含文件 STDDEF.H 中定义的整数类型。不过我没在stddef.h中找到size_t的定义,但是从stddef.h包含的头文件crtdefs.h中找到了它的定义(我使用的编译器是VS2013中的VC的编译器):

#ifndef _SIZE_T_DEFINED#ifdef _WIN64typedef unsigned __int64    size_t;#else  /* _WIN64 */typedef _W64 unsigned int   size_t;#endif  /* _WIN64 */#define _SIZE_T_DEFINED#endif  /* _SIZE_T_DEFINED */

关于size_t详细信息不在这里说明。

2、sizeof的使用:

(1)操作数是类型名称

sizeof(类型名称);

输入以下代码:

printf("%lu,%lu,%lu\n",sizeof(char),sizeof(char*),sizeof(char[5]));
输出结果是:
1,8,5
可知,第一个得到的是类型所用字节数,第二个得到的是指针所占字节数,第三个得到的是数组所占字节数。

补充:

以上结果是32位系统的情况;如果是64位系统,得到的结果可能会不同。

(2)操作数是表达式

sizeof(表达式);

sizeof 表达式;

输入以下代码:

char arr[] = "i am a student!";printf("%lu,%lu,%lu,%lu,%lu,%lu\n" \    ,sizeof arr, sizeof *arr, sizeof &arr[0], \    sizeof(arr), sizeof(*arr), sizeof(&arr[0]));
输出的结果是:
16,1,8,16,1,8
可知,是否使用括号,表示的结果是相同的。第一个得到的是数组所占用的总字节数,第二个得到的是数组中的第一个元素所占用的字节数;第三个是指针所占字节数。

(3)操作数是类或结构体

以结构体为例,输入以下代码:

struct test{    int i;      //sizeof(i) = 4    int arr[3]; //sizeof(arr) = 12;    char c;     //sizeof(c) = 1;    char *str;  //sizeof(str) = 8;};int main(void) {     struct test tt[10];    printf("%lu,%lu,%lu,%lu\n", \        sizeof(tt[0].i), sizeof(tt[0].arr), \        sizeof(tt[0].c), sizeof(tt[0].str));    printf("%lu,%lu,%lu,%lu\n", \sizeof(struct test), sizeof tt[0], \sizeof tt, sizeof *tt);    return 0;}
输出的结果是:
4,12,1,832,32,320,32
表面上看,一个结构体test所占据的空间应该为4+12+1+8=25,但实际上test被分配的空间是32。其原因与结构体分配内存空间时的对齐原则有关。具体细节见《C语言中结构体的对齐规则》。

类的情况与结构体的类似。

3、通过宏实现sizeof的定义

关于这点方法,是从帖子“谁知道sizeof这个关键字的源码实现在哪个地方可以找到?”中得到的启发。

输入以下代码:

#define sizeof1(type)   ((char*)((type*)0+1)-(char*)0)#define sizeof2(var)    ((char*)(&var+1)-(char*)&var)int main(void) {     int i;    char c;    double d;    printf("%lu, %lu.\n",sizeof1(char), sizeof2(c));    printf("%lu, %lu.\n",sizeof1(int), sizeof2(i));    printf("%lu, %lu.\n",sizeof1(double), sizeof2(d));return 0;}
输出的结果是:
1, 1.4, 4.8, 8.
表示定义没有问题。

注意事项
因为sizeof操作符在编译过程中就确定了,所以有一些注意事项。

(1)关于sizeof(i++)

sizeof在编译的时候取得是i这个变量的类型所占的空间,因为在编译的时候就被i的字节数代替了,所以不会再进行自加操作。

(2)运算符永远不会产生0

当类为空或指向空指针时,输入以下代码:

class Test1{};class Test2{    int i;    char c;    double d;};int main() {Test1 *t1 = NULL, *pt1 = new Test1;Test2 *t2 = NULL, *pt2 = new Test2;cout << sizeof(*t1) << ", " << sizeof(*pt1) << "\n";cout << sizeof(*t2) << ", " << sizeof(*pt2) << "\n";return 0;}
输出结果为:
1, 116, 16
(3)运算符不能用于的操作数
  • 函数(但sizeof可以应用于指向函数的指针)
  • 位域
  • 未定义的类
  • void类型
  • 动态分配的数组
  • 外部数组
  • 不完整类型
  • 带括号的不完整类型的名称

总之sizeof适用的操作数是能够在编译步骤中确定下来的数,是静态的。

(4)数组中的元素数量

直接上代码:

#define GetLen(arr) sizeof(arr)/sizeof(arr[0])int main() {char str[] = "This is a string.";cout << "The length of str is: " << GetLen(str) << endl;return 0;}
输出结果是:
The length of str is: 18

原创粉丝点击