簡體   English   中英

sizeof 取兩個 arguments

[英]sizeof taking two arguments

In C.1.3 of the C++ IS (2003. It's in the C++11 IS, too), the standard points out a difference between ISO C and C++; 即,對於

char arr[100];

sizeof(0, arr)在 C 中返回sizeof(char*) ,但在 C++ 中返回100

我找不到有關sizeof服用兩個 arguments 的文檔。 明顯的后備是逗號運算符,但我不這么認為: C 中的sizeof(arr)100 sizeof(0, arr)sizeof(char*) 在 C++ 中sizeof(0, arr)sizeof(arr)都是100

在這種情況下,我可能會錯過 IS 的全部意義。 任何人都可以幫忙嗎? 這類似於 09 年討論的一個問題,但沒有人提到 IS,而且我認為沒有給出正確的答案。


編輯:實際上,IS 是在談論逗號運算符。 因此,由於某種原因(0, arr)在 C 中返回一個char* ,但在 C++ 中返回一個char[100] 為什么?

在 C 中,逗號運算符不會產生左值,因此作為左值的數組arr會衰減為作為右值的指針類型(在這種情況下)。 因此,由於左值到右值的轉換sizeof(0,arr)變得等同於sizeof(char*)

但是在 C++ 中,逗號運算符產生一個左值。 沒有左值到右值的轉換。 所以sizeof(0,arr)保持不變,相當於sizeof(char[100])

順便說一句, sizeof不是 function,它是一個運算符。 所以以下是完全有效的 C++ (和 C,如果你想象printf而不是cout ):

int a[100], b[200], c[300], d[400];
cout << sizeof(a,b,c,d) << endl;

演示: http://www.ideone.com/CtEhn

您可能認為我已經將 4 個操作數傳遞給sizeof ,但這是錯誤的。 sizeof對逗號運算符的結果進行操作。 由於有許多逗號運算符,您會看到許多操作數。

4 個操作數和 3 個逗號運算符; 就像在1+2+3+4中一樣,有 3 個運算符,4 個操作數。

以上等價於以下內容(在 C++0x 中有效):

auto & result = (a,b,c,d); //first all comma operators operate on the operands.
cout << sizeof (result) << endl; //sizeof operates on the result

演示: http://www.ideone.com/07VNf

所以是逗號操作符讓你覺得有很多arguments 這里逗號是一個運算符,但在 function 調用中,逗號不是運算符,它只是參數分隔符。

function(a,b,c,d); //here comma acts a separator, not operator.

因此sizeof(a,b,c,d),運算符的結果類型進行操作,與sizeof(1+2+3+4)+運算符的結果類型完全相同。

另請注意,您不能編寫sizeof(int, char, short) ,正是因為逗號運算符無法對types進行操作。 它只對價值起作用。 我認為, sizeof是 C 和 C++ 中唯一的運算符,它也可以對類型進行操作。 在 C++ 中,多了一個可以對類型進行操作的運算符。 它的名字是typeid

在 C 中,由於逗號運算符與右值和左值相關的不同規范(不是唯一可以找到這種差異的地方),因此數組正在衰減為指針。 在 C++ 中,數組保持為數組,從而產生正確的結果。

它是一個逗號運算符。 您所說的差異與sizeof完全無關。 C 和 C++ 語言之間的區別實際上在於左值到右值、數組到指針和類似的衰減行為。

C 語言在這方面相當容易觸發:arrays 幾乎立即衰減到指針(除了極少數特定上下文),這就是為什么0, arr表達式的結果具有char *類型。 它相當於0, (char *) arr

在 C++ 語言 arrays 中,它們的“排列”時間更長。 在上下文中使用時,運算符 arrays 不會衰減為指針(左值不會衰減為右值),這就是為什么在 C++ 中的類型為0, arr表達式仍然是char[100]的原因。

這就是解釋該示例中sizeof行為差異的原因。 ?: operator 是另一個展示衰減行為相似差異的運算符示例,即sizeof(0? arr: arr)將在 C 和 C++ 中給出不同的結果。 基本上,這一切都源於 C 運算符通常不保留其操作數的左值性這一事實。 許多運算符可用於演示此行為。

這不是采取兩個sizeof的大小。 sizeof是一個運算符,而不是 function。

考慮到(0, arr)是使用逗號運算符的表達式,其他一切都到位。

查看此處可能發生的情況的最佳方法是查看標准中的語法。 如果我們查看 C99 標准草案第6.5.3一元運算符1段,我們可以看到 sizeof 的語法是:

sizeof unary-expression
sizeof ( type-name )

所以第二個不適用,但sizeof unary-expression在這種情況下如何應用? 如果我們查看標准草案中的A.2.1表達式部分並像這樣處理語法:

unary-expression -> postfix-expression -> primary-expression -> ( expression )

我們得到了表達式周圍的括號,現在我們只需要查看6.5.17逗號運算符中的逗號運算符的語法,我們就會看到:

expression:
  assignment-expression
  expression , assignment-expression

所以我們現在有:

sizeof( expression , assignment-expression )
                   ^
                   |
                   comma operator

表達式賦值表達式都可以將我們帶到具有以下語法的主表達式

primary-expression:
  identifier
  constant
  string-literal
  ( expression )

0是一個常數arr是一個標識符,所以我們有:

 sizeof( constant , identifier )

那么逗號運算符在這里做什么呢? 6.5.17節第2段說:

逗號運算符的左操作數被評估為 void 表達式; 在其評估之后有一個序列點。 然后對右操作數求值; 結果有它的類型和值。 97)

因為逗號運算符不是數組未轉換為指針的異常之一,它會產生一個指針(這在第6.3.2.1Lvalues、arrays 和 function 指示符中有介紹),這意味着我們最終得到:

sizeof( char * )

C++中,語法非常相似,所以我們在同一個地方結束,但逗號運算符的工作方式不同。 C++ 標准草案第5.18逗號運算符說:

[...]結果的類型和值是右操作數的類型和值; 結果與其右操作數具有相同的值類別[...]

所以不需要數組到指針的轉換,所以我們最終得到:

sizeof( char[100] ) 

sizeof不需要兩個 arguments。 但它也不是 function,所以(...)不要分隔 function arguments,它們只是語法的可選部分,並強制執行分組。 當您編寫sizeof(0, arr)時, sizeof的參數是單個表達式0, arr 帶有逗號運算符的單個表達式,它計算逗號左邊的表達式,拋出它的值(但不是它的副作用),然后計算逗號右邊的表達式,並使用它的值作為完整的表達。

我不確定 C,但這可能是語言之間的差異。 在 C++ 中,除非需要,否則不會發生數組到指針的轉換; 在 C 中,如果我沒記錯的話,標准說它總是發生,除非在某些情況下。 包括作為sizeof的運算符。 在這種情況下,由於逗號運算符對其操作數的類型沒有限制,因此在 C++ 中不會發生數組到指針的轉換。 在 C 中,逗號運算符的操作數未在異常中列出,因此確實發生了數組到指針的轉換。 (在這種情況下,數組是逗號運算符的操作數,而不是sizeof的操作數。)

正如一些人已經說過的,我只想添加一件事,sizeof 是一個接受表達式或強制轉換表達式的運算符。 出於這個原因,我養成了將括號寫入 sizeof習慣,前提是它是強制轉換表達式。

 char *arr;
 struct xxx { ... } v;

我會寫

sizeof arr 
sizeof v

sizeof (struct xxx)       /* Note the space after the sizeof, it's important */
sizeof (char *)

我對return no 括號做同樣的事情,因為它不是 function 調用,如果我放括號,那是因為下面的表達式需要它們。

暫無
暫無

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

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