代码改变世界

sizeof运算符的功能与限制总结

2010-12-16 00:15  Rollen Holt  阅读(3888)  评论(4编辑  收藏  举报

 关于sizeof运算符我以前也有过一些总结,这次只是稍微补充一下。对于以前的东西请看下面:

[原创]整理关于sizeof 运算符

http://saturnman.blog.163.com/blog/static/5576112010129857634/

初识元编程,再次认识sizeof运算符[原创]

http://saturnman.blog.163.com/blog/static/55761120107215259147/

 

一、sizeof运算符的工作过程序。

 1.   sizeof运算符是接受的参是类型,或是变量(如果是表达式,则按表达式结果的类型计算),如果是实参是类型那么sizeof得到的结果是此类型的大小,以byte为单位,如是实参是变量,那么sizeof得到的结果是此变量的类型的大小,以byte为单位(这里不讨论typeid这种,因为它在不同的编译器上的实现方式差异很大,难以找到统一的结论)。sizeof的返回值类型是const std::size_t,但是它永远会比0大。

2.   sizeof真正计算的时间是编译期,由编译器把sizeof的结果计算好放入相对应的位址,过量使用sizeof运算符也不会对系统性能产生不利影响。

考虑如下代码:

//code #1

const size_t val = 4;

int arr[val];

//code #2

int arr[sizeof(int)];

如果sizeof(int)的结是为4那么上面的code #1和code #2几乎没有差别(差别还是有一些,尽管有时它们产生的汇编代码都是相同的,但有时可能不同)。

3.   C++中的类型其实十分微妙细小,有时会有不经意的转换,这些在某些情况下会产生误解。也许只有对其深入理解才能准确把握其中的奥妙吧,在这里我只举一个十分常见的而且不认真的学习者经常犯的错误,只给出代码,请读者自行体会。

#include<iostream>

using namespace std;

//fun #1

int foo1(int* arr)

{

    return sizeof(arr);

}

//fun #2

int foo2(int arr[])

{

    return sizeof(arr);

}

//fun #3

template<int N>

int foo3(int(&arr) [N])

{

    return sizeof(arr);

}

int  main()

{

    int arr[]={1,2,3,4,5,6};

    int* p_arr = arr;                  //type conversion

    cout<<"sizeof(arr)="<<sizeof(arr)<<endl;

    cout<<"sizeof(p_arr)="<<sizeof(p_arr)<<endl;

    cout<<"call #1 ="<<foo1(arr)<<endl;//type conversion

    cout<<"call #2 ="<<foo2(arr)<<endl;//type conversion

    cout<<"call #3 ="<<foo3(arr)<<endl;

    return 0;

}

 

 

结果:

sizeof(arr)=24

sizeof(p_arr)=4

call #1 =4

call #2 =4

call #3 =24

二、sizeof运算符的使用限制

    如果牢记sizeof运算符的运算的静态性和用法,一般不易犯什么错,不过还时有几点指出,一般这些错误编译器都会帮你找出的,不用担心。

  1. 对于函数指针的使用

    常规函数指针和数据指针的大小一般是一样大的,如果是类的非静态成员函数则可能会出现比一般指针大的情况,这个一般不是问题。但是有时粗心的人会把函数指针和表达式搞错。如下面的代码,同样不解释,自行体会。

#include<iostream>

using namespace std;

void test_1()

{

   

}

int test_2()

{

   

}

int main()

{

    void (*pf1)();

    int  (*pf2)();

    cout<<"sizeof(pf1)="<<sizeof(pf1)<<endl;    //function pointer

    cout<<"sizeof(pf2)="<<sizeof(pf2)<<endl;    //function pointer

    cout<<"sizeof(test_1())="<<sizeof(test_1())<<endl;//expression

    //same as sizeof(void)

    cout<<"sizeof(test_2())="<<sizeof(test_2())<<endl;//expression

    //same as sizeof(int)

    cout<<"sizeof(void)="<<sizeof(void)<<endl;  //void

    return 0;

}

 

 

结果:

sizeof(pf1)=4

sizeof(pf2)=4

sizeof(test_1())=1

sizeof(test_2())=4

sizeof(void)=1

这个给出了一些warning

C:\Users\saturnman\cpp>g++ function_sizeof.cpp

function_sizeof.cpp: In function 'int main()':

function_sizeof.cpp:17:44: warning: invalid application of 'sizeof' to a void type

function_sizeof.cpp:21:36: warning: invalid application of 'sizeof' to a void type

2. 对于递归sizeof的违例

        由于sizeof是在编译期计算,想想如果一个类成员大小由一个sizeof表达式计算得到,并且此sizeof计算的就是本类的大小,那么将形成递归的sizeof,此时sizeof运算符是不能完成工作的。考虑如下代码:

#include<iostream>

using namespace std;

class A

{

    public:

    int a[sizeof(*this)];//error

   

    void test()

    {

        int a[sizeof(*this)];

    }

};

int main()

{

    return 0;

}

编译时会产生如下错误:

sizeof_class.cpp:6:19: error: invalid use of 'this' at top level

而处在类成员函数中有的相同代码就没有出错,读者可以想想这是为什么。

3. 对于编译期和运行期计算相同表达式的结果可能并不相同,考虑如下代码:

bool f()

{

    char array[1+int(1+0.2-0.1-0.1)];

    int size = 1+int(1+0.2-0.1-0.1);

    return sizeof(array)==size;

}

// it is unspecified whether the value of f() will be true or false.

sizeof(array)的值要Re

sizeof(array)的值要在编译时计算int(1+0.2-0.1-0.1),但是size变量的值可能是运行期才计算出来的,并没有人或是什么标准可以保证这两个时时期计算相同的表达式会产生相同的结果,因此上面的函数的返回值是不确定的。

[1] Programming Language C++ ISO/IEC JTC1 SC22 WG21 N3092

源文档:http://saturnman.blog.163.com/blog/static/55761120101113115756305/