sizeof运算符是如何在c ++中实现的?

时间:2009-04-05 12:55:03

标签: c++

有人能指出我在C ++中实现sizeof运算符以及有关其实现的一些描述。

sizeof是无法重载的运算符之一。

那么这意味着我们无法改变其默认行为吗?

8 个答案:

答案 0 :(得分:25)

sizeof不是C ++中的真正运算符。它只是特殊的语法,它插入一个等于参数大小的常量。 sizeof不需要或没有任何运行时支持。

编辑:您想了解如何确定查看其定义的类/结构的大小吗?对此的规则是ABI的一部分,编译器只是实现它们。基本上规则由

组成
  1. 原始类型的大小和对齐定义;
  2. 各种指针的结构,大小和对齐方式;
  3. 结构中包装字段的规则;
  4. 关于虚拟表相关内容的规则(更深奥)。
  5. 但是,ABI是平台的,通常是特定于供应商的,即在x86和(比如)IA64上,A的大小将不同,因为IA64不允许未对齐的数据访问。

    struct A
    {
        char i ;
        int  j ;
    } ;
    
    assert (sizeof (A) == 5)  ; // x86, MSVC #pragma pack(1)
    assert (sizeof (A) == 8)  ; // x86, MSVC default
    assert (sizeof (A) == 16) ; // IA64
    

答案 1 :(得分:14)

http://en.wikipedia.org/wiki/Sizeof

基本上,引用Bjarne Stroustrup's C++ FAQ

  

无法重载Sizeof,因为内置操作(例如将指针递增到数组)会隐式依赖于它。考虑:

X a[10];
X* p = &a[3];
X* q = &a[3];
p++;    // p points to a[4]
    // thus the integer value of p must be
    // sizeof(X) larger than the integer value of q
  

因此,sizeof(X)无法给出   新的和不同的意义   程序员没有违反基本   语言规则。

答案 2 :(得分:7)

不,你无法改变它。您希望从实现它的过程中学到什么?

使用更基本的操作无法用C ++编写sizeof。它不是一个函数,也不是库标题的一部分,例如printfmalloc。它在编译器中。

编辑:如果编译器本身是用C或C ++编写的,那么你可以认为实现是这样的:

size_t calculate_sizeof(expression_or_type)
{
   if (is_type(expression_or_type))
   {
       if (is_array_type(expression_or_type))
       {
           return array_size(exprssoin_or_type) * 
             calculate_sizeof(underlying_type_of_array(expression_or_type));
       }
       else
       {
           switch (expression_or_type)
           {
                case int_type:
                case unsigned_int_type:
                     return 4; //for example
                case char_type:
                case unsigned_char_type:
                case signed_char_type:
                     return 1;
                case pointer_type:
                     return 4; //for example

                //etc., for all the built-in types
                case class_or_struct_type:
                {
                     int base_size = compiler_overhead(expression_or_type);
                     for (/*loop over each class member*/)
                     {
                          base_size += calculate_sizeof(class_member) +
                              padding(class_member);
                     }
                     return round_up_to_multiple(base_size,
                              alignment_of_type(expression_or_type));
                }
                case union_type:
                {
                     int max_size = 0;
                     for (/*loop over each class member*/)
                     {
                          max_size = max(max_size, 
                             calculate_sizeof(class_member));
                     }
                     return round_up_to_multiple(max_size,
                            alignment_of_type(expression_or_type));
                }
           }
       }
   }
   else
   {
       return calculate_sizeof(type_of(expression_or_type));
   }
}

注意是非常多的伪代码。我没有包括很多东西,但这是一般的想法。编译器可能实际上并不这样做。它可能会计算类型(包括类)的大小并存储它,而不是每次写sizeof(X)时重新计算。它也允许例如指针的大小取决于他们指向的内容。

答案 3 :(得分:5)

sizeof在编译时完成它的工作。运算符重载只是函数,并且在运行时执行它们的操作。因此,即使C ++标准允许,也不可能使sizeof超载。

答案 4 :(得分:3)

sizeof是一个编译时运算符,这意味着它在编译时进行求值。

它不能重载,因为它已经在所有用户定义的类型上有意义 - sizeof()类是类定义的对象在内存中占用的大小,而sizeof()是变量的大小变量名称占用的对象在内存中。

答案 5 :(得分:1)

除非您需要了解如何计算特定于C ++的大小(例如为v-table分配),否则您可以查看Plan9的C编译器。它比试图解决g ++简单得多。

答案 6 :(得分:1)

变量:

#define getsize_var(x) ((char *)(&(x) + 1) - (char *)&(x))

类型:

#define getsize_type(type) ( (char*)((type*)(1) + 1) - (char*)((type *)(1)))

答案 7 :(得分:-1)

查看Gnu C++ compiler 的来源,真实地了解这是如何完成的。