在C ++ IS的C.1.3中(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*)
。 C ++中sizeof(0, arr)
和sizeof(arr)
都是100
。
在这种情况下,我可能会忽略IS的重点。有人可以帮忙吗?这类似于09年讨论的问题,但没有人提到IS,我认为没有给出正确答案。
编辑:实际上,IS正在谈论逗号运算符。因此,出于某种原因(0, arr)
在C中返回char*
,在C ++中返回char[100]
。为什么呢?
答案 0 :(得分:46)
在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
。
答案 1 :(得分:23)
在C中,然后数组衰减为指针,因为逗号运算符与rvalues和lvalues的关系不同(不是唯一可以找到这种差异的地方)。在C ++中,数组保持一个数组,产生正确的结果。
答案 2 :(得分:6)
这是一个逗号运算符。你所谈论的差异与sizeof
完全无关。区别在于左值到右值,数组到指针以及C和C ++语言之间类似的衰减行为。
0, arr
表达式的结果具有char *
类型的原因。它相当于0, (char *) arr
。
在C ++语言中,数组保持它们的“数组”更长。在,
运算符数组的上下文中使用时,不会衰减为指针(并且左值不会衰减为rvalues),这就是为什么在C ++中0, arr
表达式的类型仍为char[100]
这就解释了该示例中sizeof
行为的差异。 ?:
运算符是运算符的另一个示例,它演示了衰减行为的类似差异,即sizeof(0 ? arr : arr)
将在C和C ++中给出不同的结果。基本上,这一切都源于C运算符通常不保留其操作数的左值。很多运算符都可以用来证明这种行为。
答案 3 :(得分:5)
这不是sizeof
两个论点。 sizeof
是一个运算符,而不是一个函数。
考虑(0, arr)
是使用逗号运算符的表达式,其他所有内容都将落实到位。
答案 4 :(得分:3)
sizeof
没有两个参数。但它也不是一个功能,
所以(...)
不分界函数参数,它们只是一个
语法的可选部分,并强制执行分组。当你写作
sizeof(0, arr)
,sizeof
的参数是单个表达式0,
arr
。带有逗号运算符的单个表达式,用于计算
逗号左边的表达式抛出它的值(但不是它的值)
副作用),然后评估逗号右边的表达式,
并使用其值作为完整表达式的值。
我不确定C,但这可能是一个区别
汉语语言。在C ++中,除非发生数组到指针的转换
这是必需的;在C中,如果我没记错的话,标准就说了
总是发生在某些情况下。包括作为
sizeof
的运算符。在这种情况下,因为逗号运算符没有
对其操作数的类型有限制
数组到指针的转换不会发生在C ++中。在C中,一个
逗号运算符的operatand没有在例外中列出,所以
数组到指针的转换确实发生了。 (在这种情况下,阵列
是逗号运算符的操作数,而不是sizeof
的操作数。)
答案 5 :(得分:2)
查看可能发生的事情的最佳方法是查看标准中的语法。如果我们查看草案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
逗号运算符<的逗号运算符的语法/ em>我们看到了:
expression:
assignment-expression
expression , assignment-expression
所以我们现在有:
sizeof( expression , assignment-expression )
^
|
comma operator
表达式和赋值表达式都可以将我们带到 primary-expression ,它具有以下语法:
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] )
答案 6 :(得分:1)
正如几位已经说过的那样,我只想添加一个东西,sizeof是一个运算符,它采用表达式或强制转换表达式。 出于这个原因,我习惯于将paranthesis写为sizeof only ,如果它是一个强制转换表达式。
char *arr;
struct xxx { ... } v;
我会写
sizeof arr
sizeof v
但是
sizeof (struct xxx) /* Note the space after the sizeof, it's important */
sizeof (char *)
我对return
没有括号做同样的事情,因为它不是函数调用,如果我把括号括起来,因为下面的表达式需要它们。