【问题标题】:Why sizeof int is wrong, while sizeof(int) is right?为什么 sizeof int 是错误的,而 sizeof(int) 是正确的?
【发布时间】:2012-10-29 11:11:12
【问题描述】:

我们知道sizeof是用于计算任何数据类型和表达式大小的运算符,当操作数是表达式时,括号可以省略。

int main()
{
        int a;

        sizeof int;
        sizeof( int );
        sizeof a;
        sizeof( a );

        return 0;
}

sizeof 的第一个用法是错误的,而其他的是正确的。

使用gcc编译时会报如下错误信息:

main.c:5:9: error: expected expression before ‘int’

我的问题是为什么 C 标准不允许这种操作。 sizeof int 会引起歧义吗?

【问题讨论】:

  • 有趣的是,并非所有的表达式都可以不带括号:试试sizeof (int)a
  • @MikkelK.:OP 正在询问标准引号背后的推理,他已经知道标记答案中提到的引号。
  • @Lundin: sizeof +(int)a*& 具有实际编译的优势 ;-)
  • @SteveJessop 嗯,它不是左值。虽然它确实在 Embarcadero C++ 中编译,但很奇怪。无论如何,我相信我们刚刚找到了一元 + 运算符的用途!这一定是 C 编程历史上的第一次 :)
  • @Lundin:你还是要小心一元+。例如,sizeof +(char)a == sizeof(int) 由于整数提升,如果您完全不担心您试图取其大小的表达式,只需放入括号就可能不太容易出错。所以我不确定我是否会称其为“用途”,尽管我承认我确实使用过它......

标签: c++ c sizeof


【解决方案1】:

以下内容可能不明确:

sizeof int * + 1

(sizeof (int*)) + 1,还是(sizeof(int)) * (+1)

显然 C 语言本可以引入一个规则来解决歧义,但我可以想象为什么它没有打扰。就目前的语言而言,类型说明符永远不会“裸露”地出现在表达式中,因此不需要规则来确定第二个 * 是类型的一部分还是算术运算符。

现有语法确实已经解决了sizeof (int *) + 1 的潜在歧义。是(sizeof(int*))+1不是sizeof((int*)(+1))

C++ 有一个类似的问题需要用函数式强制转换语法来解决。你可以写int(0),你可以写typedef int *intptr; intptr(0);,但是你不能写int*(0)。在这种情况下,解决方案是“裸”类型必须是一个简单的类型名称,它不能只是任何可能包含空格或尾随标点符号的旧类型 ID。也许sizeof 可以定义相同的限制,我不确定。

【讨论】:

  • C++ 有 new int*(X) 如果 C++ 没有指定新运算符采用可能是类型的最长字符串,这将是模棱两可的。所以在 C++ 中,我猜他们可以用 sizeof 做同样的事情。但在 C++ 中,您可以说 sizeof int(),这将是模棱两可的(类型或值初始化为 int?)。
  • @JohannesSchaub-litb:嗯,所以也许 C++ 可以说如果可以解析一个类型是首选类型,否则它是一个表达式。歧义将得到解决,但 sizeof int() 格式不正确(“size_t 没有 operator()”),我预计这将是不受欢迎的!
【解决方案2】:

来自C99 Standard

6.5.3.4.2
sizeof 运算符产生其操作数的大小(以字节为单位),它可以是表达式或带括号的名称 输入。

在您的情况下,int 既不是表达式也不是带括号的名称。

【讨论】:

  • 我不明白为什么这会得到 7 个赞。与删除的三个答案一样,它只是重复规则而不是解释规则存在的原因。
  • @larsmans,是的,我同意你的看法。虽然它继续重复规则,但至少,它给出了一个授权阅读。
  • @larsmans 如果我们开始尝试证明在 C99 中做出的每一个决定都是合理的,我们将一整年都在这里。引用标准是结束本次讨论的最佳方式。
  • @Perry:如果你不喜欢这种问题,你可以投票结束这个问题。
  • 作为一个非C++从业者,即使我理解这个答案,不知道如果你能阅读和理解英语是什么问题。
【解决方案3】:

在C语言中有两种使用sizeof操作符的方法。语法是这样的:

C11 6.5.3 Unary operators
...
sizeof unary-expression
sizeof ( type-name )

当你使用一个类型作为操作数时,你必须有括号,根据语言的语法定义。如果在表达式上使用 sizeof,则不需要括号。

C 标准提供了一个这样的示例,说明您可能希望在表达式中使用它:

sizeof array / sizeof array[0]

但是,为了保持一致性,并避免与运算符优先级相关的错误,我个人建议在任何情况下都始终使用 ()。

【讨论】:

  • @JohannesSchaub-litb 我同意它没有为 C 标准委员会在指定 C90 标准时的推理方式提供任何理由。你必须问他们......它确实在没有提供任何理由的情况下回答,但是,C 不允许这样做,因为语法在 6.5.3 中指定。 OP 似乎也没有意识到 sizeof expressionsizeof(type) 之间的区别,这在这个答案中有解释。
  • (作为记录,我只是阅读了 C90 和 C11 的基本原理,都没有提供任何解释。)
  • 我怀疑没有必要的理由,这只是最初的 C 设计者决定这样做的方式。也许它使早期的解析器变得更容易。我将发布关于 typedef 和变量共享相同命名空间这一事实的答案,但这并不排除允许第一种语法;它只需要解析规则说它在没有括号时更喜欢变量,在有括号时更喜欢类型,并且当名称明确时可以使用任何一种形式。由于无需更改它,标准委员会就不管它了。
猜你喜欢
  • 2013-09-24
  • 2012-06-14
  • 1970-01-01
  • 2010-11-09
  • 1970-01-01
  • 1970-01-01
  • 2012-10-09
  • 2011-03-07
相关资源
最近更新 更多