簡體   English   中英

c++中sizeof運算符是如何實現的?

[英]How is the sizeof operator implemented in c++?

有人可以向我指出 C++ 中 sizeof 運算符的實現以及有關其實現的一些描述。

sizeof 是不能重載的運算符之一。

所以這意味着我們不能改變它的默認行為?

sizeof不是 C++ 中的真正運算符。 它只是插入一個等於參數大小的常量的特殊語法。 sizeof不需要或有任何運行時支持。

編輯:您想知道如何通過定義來確定類/結構的大小嗎? 這方面的規則是ABI 的一部分,編譯器只是實現它們。 基本上規則包括

  1. 原始類型的大小和對齊定義;
  2. 各種指針的結構、大小和對齊方式;
  3. 在結構中打包字段的規則;
  4. 關於虛擬表相關內容的規則(更深奧)。

但是,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

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

基本上,引用Bjarne Stroustrup 的 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) 一個新的和不同的含義。

不,你不能改變它。 你希望從它的實現中學到什么?

sizeof不能使用更基本的操作用 C++ 編寫。 它不是函數,也不是像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)時重新計算。 例如,還允許根據指針指向的內容具有不同大小的指針。

sizeof 做它在編譯時做的事情。 運算符重載只是函數,並在運行時執行它們所做的操作。 因此,即使 C++ 標准允許,也不能重載 sizeof。

sizeof 是一個編譯時運算符,這意味着它是在編譯時計算的。

它不能被重載,因為它已經對所有用戶定義的類型有意義——一個類的 sizeof() 是該類定義的對象在內存中的大小,而 sizeof() 一個變量是該對象的大小變量名占用內存。

多變的:

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

類型:

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

除非您需要了解 C++ 特定的大小是如何計算的(例如 v-table 的分配),否則您可以查看 Plan9 的 C 編譯器。 這比嘗試解決 g++ 簡單得多。

請查看Gnu C++ 編譯器的源代碼,以了解這是如何完成的。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM