为什么sizeof被认为是一个运算符?

114

为什么sizeof被认为是一个运算符而不是一个函数?

哪种属性才能使其有资格成为运算符?

10个回答

206
因为C标准规定了这样做,并且它是唯一的表决者。
因此产生了以下后果:
- sizeof的操作数可以是括号中的类型,例如sizeof (int),而不是对象表达式。 - 括号是不必要的:int a; printf("%d\n", sizeof a); 是完全正常的。它们通常出现的原因首先是因为它们作为类型转换表达式的一部分是必需的,其次是因为sizeof的优先级非常高,因此 sizeof a + b 不同于 sizeof (a+b)。但是它们不是sizeof调用的一部分,而是操作数的一部分。 - 无法取sizeof的地址。 - sizeof操作数的表达式在运行时不会被求值(sizeof a++ 不会修改a)。 - sizeof操作数的表达式可以是除了void或函数类型以外的任何类型。实际上,这就是sizeof的重点。
如果将sizeof作为一个函数,那么它与函数在所有上述方面都有所不同。可能还有其他函数和一元运算符之间的差异,但我认为这已足以证明即使想让sizeof成为函数也不可能。

3
哇,正好是我在想的! - crashmstr
我认为现在的事情更加复杂,因为有可变长度数组(VLA)。如果表达式中有VLA,标准甚至允许sizeof具有副作用。 - Aaron McDaid
@glglgl 不,那没有任何意义。在这种情况下,(int)只是括号内的类型名称,没有什么花哨的东西。这里的括号是sizeof语法的一部分 - 在获取类型大小时需要它们,但在获取表达式大小时不需要它们。例如,请参见此处 - anatolyg
@anatolyg 我的评论是很久以前的了,我想当时我是在尝试讽刺。 - glglgl
3
标准使用两种符号表示 sizeofsizeof 一元表达式sizeof (类型名) — 因此在 C11 标准中,它不被认为是“强制转换”,而是带圆括号的类型名。最终结果大致相同。(作为比较,强制转换表达式为 (类型名) 强制转换表达式。)我讨厌注释 Markdown 与问答 Markdown 的差异工作方式! - Jonathan Leffler
2
printf("%d\n", sizeof a) 并不完全正确。%d 是错误的说明符,它具有未定义的行为。 - Ayxan Haqverdili

29

如果它是一个运算符而不是函数,它可以用作编译时常量。例如:

union foo {
    int i;
    char c[sizeof(int)];
};

从语法上来说,如果它不是运算符,那么它必须是预处理器宏,因为函数不能将类型作为参数。这将是一个难以实现的宏,因为 sizeof 可以将类型和变量作为参数。


5
+1,但需要注意当参数是VLA(可变长度数组)时,它不是编译时常量。 - Jonathan Leffler

7
因为C标准是这样规定的,并且它拥有唯一的投票权。而且标准可能是正确的,因为sizeof需要一个类型。
通常情况下,如果函数的定义域或值域(或两者都)包含比实数更复杂的元素,则称该函数为操作符。相反,如果函数的定义域和值域都不包含比实数更复杂的元素,则该函数很可能被简单地称为函数。余弦等三角函数就是后一种情况的例子。
此外,当某些函数被使用得如此频繁以至于它们已经演化出比一般形式F(x,y,z,...)更快捷或更容易理解的记法时,所得到的特殊形式也被称为操作符。例如中缀操作符加号"+"和除号"/"以及后缀操作符阶乘"!"。这种用法与涉及实体的复杂性无关。 (维基百科)

这可能解释了C标准(以及其他编程语言)在使用“运算符”和“函数”这些术语时的动机。 - Steve Jessop

6
因为它不是一个函数。您可以像这样使用它:
int a;
printf("%d\n", sizeof a);

函数确实有入口点、代码等。函数在运行时(或内联)运行,sizeof必须在编译时确定。


3

原因如下:

  • 当你将一个值传递给函数时,对象的大小并没有传递给函数,因此sizeof“函数”无法确定大小
  • 在C语言中,函数只能接受一种类型的参数; sizeof()需要接受各种不同的东西(变量以及类型!在C语言中不能将类型传递给函数)
  • 调用函数涉及复制参数和其他不必要的开销

2

因为它是一个编译时运算符,为了计算对象的大小,需要在编译时才能获得的类型信息。但这对于C++来说并不适用。


1

sizeof运算符是编译时实体而不是运行时实体,不需要像函数一样加括号。当代码被编译时,它会在编译时将该变量的大小替换为值,但在函数中,在函数执行后我们才会知道返回的值。


1

函数和 sizeof 的值有所不同 - sizeof 的值在编译时解析,而不是在运行时解析!


8
除了VLA(可变长度数组)参数之外。 - Jonathan Leffler

-1

sizeof() 运算符是一个编译时发生的事件。它可以用于确定参数或参数的大小。


-4

Sizeof(),我认为显然它既是一个函数又是一个运算符。为什么呢?因为在输入阶段,函数需要括号进行输入。但主要也是一个运算符,因为运算符是动作字符,因此sizeof是一个操作语句,对括号中的操作数进行操作。


标准已经明确规定sizeof是一个运算符。 - phuclv

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接