sizeof 接受两个参数

发布于 2024-11-15 02:26:34 字数 703 浏览 3 评论 0原文

在 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)100sizeof(0, arr)sizeof(char*)。在 C++ 中,sizeof(0, arr)sizeof(arr) 均为 100

在这种情况下,我可能错过了 IS 的全部要点。有人可以帮忙吗?这与09年讨论过的问题类似,但没有人提到IS,我认为没有给出正确答案。


编辑:实际上,IS 正在谈论逗号运算符。因此,出于某种原因,(0, arr) 在 C 中返回 char*,但在 C++ 中返回 char[100]。为什么?

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++; namely, for

char arr[100];

sizeof(0, arr) returns sizeof(char*) in C, but 100 in C++.

I can find no documentation for sizeof taking two arguments. The obvious fallback is the comma operator, but I don't think so: sizeof(arr) in C is 100; sizeof(0, arr) is sizeof(char*). Both sizeof(0, arr) and sizeof(arr) are 100 in C++.

I may be missing the whole point of the IS in this context. Can anyone help? This is similar to a question discussed back in '09, but no one referred to the IS, and I don't think the correct answer was given.


Edit: Actually, the IS is talking about the comma operator. So, for some reason (0, arr) returns a char* in C, but a char[100] in C++. Why?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(7

她说她爱他 2024-11-22 02:26:34

在 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), 运算符结果的类型进行运算,完全相同的方式,< code>sizeof(1+2+3+4) 对 + 运算符结果的类型进行运算。

另请注意,您不能编写sizeof(int, char, short),正是因为逗号运算符无法对类型。它仅对起作用。我认为,sizeof 是 C 和 C++ 中唯一可以对类型进行操作的运算符。在 C++ 中,还有一个可以对类型进行操作的运算符。它的名称是typeid

In C, comma operator doesn't produce an lvalue, consequently the array arr which is an lvalue decays into a pointer type which is a rvalue (in this case). So sizeof(0,arr) becomes equivalent to sizeof(char*), due to lvalue-to-rvalue conversion.

But in C++, comma operator produces an lvalue. There is no lvalue-to-rvalue conversion. So sizeof(0,arr) remains same, which is equivalent to sizeof(char[100]).

By the way, sizeof is not a function, it's an operator. So the following is completely valid C++ (and C, if you imagine printf instead of cout):

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

Demo : http://www.ideone.com/CtEhn

You might think that I've passed 4 operands to sizeof but that is wrong. sizeof operates on the result of the comma operators. And its because of the many comma operators you see many operands.

4 operands with 3 comma operators; just like in 1+2+3+4, there're 3 operators, 4 operands.

The above is equivalent to the following (valid in 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

Demo : http://www.ideone.com/07VNf

So it's the comma operator which makes you feel that there are many arguments. Here comma is an operator, but in function call, comma is NOT an operator, its simply argument separator.

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

So sizeof(a,b,c,d) operates on the type of the result of , operators, exactly in the same way, sizeof(1+2+3+4) operates on the type of the result of + operators.

Also note that you cannot write sizeof(int, char, short), precisely because comma operator cannot operate on types. It operates on value only. I think, sizeof is the only operator in C and C++, which can operate on types as well. In C++, there is one more operator which can operates on types. Its name is typeid.

愛上了 2024-11-22 02:26:34

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

In C then the array is decaying to a pointer, because of the different specification of the comma operator with relation to rvalues and lvalues (not the only place such a difference can be found). In C++ then the array stays an array, yielding the correct result.

口干舌燥 2024-11-22 02:26:34

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

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

在 C++ 语言中,数组可以更长时间地保留“数组性”。当在 , 上下文中使用时,运算符数组不会衰减为指针(左值不会衰减为右值),这就是为什么在 C++ 中类型为 0, arr表达式仍然是char[100]

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

It is a comma operator. And the difference you are talking about has absolutely nothing to do with sizeof. The difference is really in lvalue-to-rvalue, array-to-pointer and similar decay behaviors between C and C++ languages.

C language is rather trigger-happy in this regard: arrays decay to pointers practically immediately (with the exception of very few specific contexts), which is why the result of 0, arr expression has char * type. It is equivalent to 0, (char *) arr.

In C++ language arrays preserve they "arrayness" much longer. When used in the context of , operator arrays don't decay to pointers (and lvalues do not decay to rvalues), which is why in C++ the type of 0, arr expression is still char[100].

This is what explains the difference in sizeof behavior in that example. ?: operator is another example of an operator that demonstrates the similar difference in decay behavior, i.e. sizeof(0 ? arr : arr) will give you different results in C and C++. Basically, it all stems from the fact that C operators don't usually preserve the lvalueness of their operands. A lot of operators can be used to demonstrate this behavior.

压抑⊿情绪 2024-11-22 02:26:34

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

考虑一下 (0, arr) 是一个使用逗号运算符的表达式,其他一切都就位了。

This is not sizeof taking two arguments. sizeof is an operator, not a function.

Consider that (0, arr) is an expression using the comma operator, and everything else falls into place.

云裳 2024-11-22 02:26:34

了解这里可能发生的情况的最佳方法是查看标准中的语法。如果我们查看 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)

由于逗号运算符不是数组不转换为指针的例外情况之一,因此它会生成一个指针(这在第 < 节中介绍) /em> 6.3.2.1 左值、数组和函数指示符),这意味着我们最终得到:

sizeof( char * )

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

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

,因此不需要数组到指针的转换,因此我们最终得到:

sizeof( char[100] ) 

The best way to see what could be going on here is look at the grammar in the standard. If we look at the draft C99 standard section 6.5.3 Unary operators paragraph 1 we can see that the grammar for sizeof is:

sizeof unary-expression
sizeof ( type-name )

So the second one does not apply but how does the sizeof unary-expression apply in this case? If we look at section A.2.1 Expressions from the draft standard and work through the grammar like so:

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

we get the parenthesizes around an expression and now we just have to look at the grammar for comma operator from section 6.5.17 Comma operator and we see:

expression:
  assignment-expression
  expression , assignment-expression

So we have now have:

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

both expression and assignment-expression can take us to primary-expression which has the following grammar:

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

and 0 is a constant and arr is an identifier so we have:

 sizeof( constant , identifier )

So what does the comma operator do here? Section 6.5.17 paragraph 2 says:

The left operand of a comma operator is evaluated as a void expression; there is a
sequence point after its evaluation. Then the right operand is evaluated; the result has its type and value.97)

since the comma operator is not one of the exceptions where a array is not converted to a pointer it yields a pointer(this is covered in section 6.3.2.1 Lvalues, arrays, and function designators) which means we end up with:

sizeof( char * )

In C++ the grammar is pretty similar so we end in the same place but the comma operators works differently. The C++ draft standard section 5.18 Comma operator says:

[...]The type and value of the result are the type and value of the right operand; the result is of the same value category as its right operand[...]

so and array-to-pointer conversion is not not required and so we end up with:

sizeof( char[100] ) 
许你一世情深 2024-11-22 02:26:34

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

我不确定C,但这可能是两者之间的区别
语言。在 C++ 中,不会发生数组到指针的转换,除非
它是需要的;在C中,如果我没记错的话,标准说它
除了在某些情况下之外,总是会发生。包括作为
sizeof 运算符。在这种情况下,由于逗号运算符不
对其操作数的类型有限制,
C++ 中不会发生数组到指针的转换。在C中,一个
逗号运算符的操作数未在例外中列出,因此
数组到指针的转换确实发生了。 (在本例中,数组
是逗号运算符的操作数,而不是 sizeof 的操作数。)

sizeof doesn't take two arguments. But it's not a function, either,
so the (...) don't delimit function arguments, they're just an
optional part of the syntax, and enforce grouping. When you write
sizeof(0, arr), the argument to sizeof is the single expression 0,
arr
. A single expression with a comma operator, which evaluates the
expression to the left of the comma, throws out its value (but not its
side effects), then evaluates the expression to the right of the comma,
and uses its value as the value of the complete expression.

I'm not sure about C, but this could be a difference between the
langauges. In C++, the array-to-pointer conversion doesn't occur unless
it is needed; in C, if I recall correctly, the standard says that it
always takes place except in certain contexts. Including as the
operator of sizeof. In this case, since the comma operator doesn't
have an constraints with regards to the types of its operands, the
array-to-pointer conversion doesn't take place in C++. In C, an
operatand of the comma operator isn't listed in the exceptions, so the
array-to-pointer conversion does take place. (In this case, the array
is an operand of the comma operator, and not of sizeof.)

夜血缘 2024-11-22 02:26:34

正如几位已经说过的,我只想添加一件事,sizeof 是一个采用表达式或强制转换表达式的运算符。
出于这个原因,我养成了在 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 做同样的事情,不带括号,因为它不是函数调用,如果我放括号,那是因为后面的表达式需要它们。

As several have already said, and I want to add only one thing, sizeof is an operator taking either an expression or a cast expression.
For this reason I took the habit to write paranthesis to a sizeof only if it is a cast expression.

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

I will write

sizeof arr 
sizeof v

but

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

I do the same with return no parenthesis, as it is not a function call, and if I put parenthesis it's because the expression following needs them.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文