大小采取两个论点

sizeof taking two arguments

本文关键字:两个      更新时间:2023-10-16

在C++IS(2003.它在C++11 IS也是(,标准指出了ISO C和C++之间的差异;即,对于

char arr[100];

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

我找不到sizeof采取两个论点的文档。明显的后备是逗号运算符,但我不这么认为:C 中的sizeof(arr)100; sizeof(0, arr) sizeof(char*).sizeof(0, arr)sizeof(arr)都在C++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不是一个函数,它是一个运算符。所以以下内容是完全有效的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

所以是逗号运算符让你觉得有很多参数。这里逗号是一个运算符,但在函数调用中,逗号不是运算符,它只是参数分隔符。

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),正是因为逗号运算符不能对类型进行操作。它仅根据价值进行操作。 我认为,sizeof 是 C 和 C++ 中唯一的运算符,它也可以对类型进行操作。在C++中,还有一个运算符可以对类型进行操作。它的名字是 typeid .

在 C 中,数组衰减为指针,因为逗号运算符相对于右值和左值的规范不同(不是可以找到这种差异的唯一地方(。在C++数组中,数组保持为数组,产生正确的结果。

它是一个

逗号运算符。而你所说的区别与sizeof完全无关.区别实际上在于 C 语言和 C++ 语言之间的左值到右值、数组到指针以及类似的衰减行为。

C 语言在这方面相当喜欢触发:数组几乎立即衰减到指针(除了极少数特定上下文(,这就是为什么0, arr表达式的结果具有char *类型。它相当于0, (char *) arr.

在C++语言数组中,它们的"数组性"保留时间要长得多。当在,运算符数组的上下文中使用时,运算符数组不会衰减到指针(并且左值不会衰减到右值(,这就是为什么在C++中0, arr表达式的类型仍然char[100]

这就是该示例中sizeof行为差异的原因。 ?:算子是另一个证明衰减行为差异的算子的例子,即 sizeof(0 ? arr : arr) 会在 C 和 C++ 中为您提供不同的结果。基本上,这一切都源于这样一个事实,即 C 运算符通常不会保留其操作数的左值。可以使用许多运算符来演示此行为。

这不是

sizeof采用两个参数。 sizeof是一个运算符,而不是一个函数。

考虑到(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、数组和函数指示符一节中介绍(,这意味着我们最终得到:

sizeof( char * )

在C++语法非常相似,所以我们在同一个地方结束,但逗号运算符的工作方式不同。C++标准草案部分5.18逗号运算符说:

[...]结果的类型和值是右操作数的类型和值;结果与其右操作数具有相同的值类别[...]

所以数组到指针的转换不是不需要的,所以我们最终得到:

sizeof( char[100] ) 

sizeof不需要两个参数。 但它也不是函数,所以(...)不分隔函数参数,它们只是一个语法的可选部分,并强制分组。 当你写的时候 sizeof(0, arr)sizeof的参数是0, arr的单个表达式。 带有逗号运算符的单个表达式,用于计算逗号左侧的表达式,抛出其值(但不是其副作用(,然后计算逗号右侧的表达式,并将其值用作完整表达式的值。

我不确定 C,但这可能是语言。 在C++中,数组到指针的转换不会发生,除非这是需要的;在 C 中,如果我没记错的话,标准说它除非在某些情况下,否则总是发生。 包括作为sizeof的运算符。 在这种情况下,由于逗号运算符没有对其操作数的类型有约束,数组到指针的转换不会在C++中进行。 在 C 中,一个逗号运算符的操作数未在异常中列出,因此确实会发生数组到指针的转换。 (在本例中,数组是逗号运算符的操作数,而不是 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做同样的事情,因为它不是函数调用,如果我加上括号,那是因为下面的表达式需要它们。