[英]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.1
節Lvalues、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.