sizeof是一个函数还是一个运算符?

7
为什么我们说sizeof(variable)是一种运算符,而不是函数?
它看起来像一个函数调用,但当我思考运算符的意义时,它给我的感觉更类似于+-*等。

7
因为sizeof(一整个单词)是一个运算符而不是函数,例如sizeof myvar。它需要用于类型的括号。 - Weather Vane
1
只有在后面跟着表达式时才需要括号。 - stark
你可以写成 x = +(y)。括号不会使 + 成为一个函数。 - William Pursell
1
这个回答解决了你的问题吗?为什么sizeof被认为是一个运算符? - phuclv
7个回答

8

这是一个运算符,你不需要使用括号,除非"操作数是类型名称时,必须用括号括起来"。这是一种语法限制,但不应与函数调用混淆。

请参见GNU 文档中的最后一个示例:

size_t a = sizeof(int);
size_t b = sizeof(float);
size_t c = sizeof(5);
size_t d = sizeof(5.143);
size_t e = sizeof a;

如果没有类型名称的括号,使用gcc编译器可能会出现以下错误:

test.c:7:20: error: expected expression before ‘int’
    7 |  size_t s = sizeof int;
      |                    ^~~

但是执行sizeof 12sizeof a是可以的。


5

它是一个运算符,因为它不像函数那样接受参数。它在语法层级上操作。

f(int) 不是一个有效的函数调用,但是 sizeof(int) 是对 sizeof 的有效使用。

它也可以作用于变量或类型,设计上非常灵活,这也是运算符可以做到的,因为它深度嵌入了 C 语言的语法中。

更多细节请在这里找到


C标准未指定int的大小。 - Eric Postpischil
@EricPostpischil 这是 C++ 的特性吗? - tadman
你是在考虑 sizeof expression 而不是 sizeof (type) 吗? - Eric Postpischil

3

根据语法所示:

unary-expression:
  postfix-expression
  ++ unary-expression
  -- unary-expression
  unary-operator cast-expression
  sizeof unary-expression
  sizeof (type-name)
  _Alignof (type-name)

unary-operator: one of
  & * + - ~ !

这是一个运算符,它不仅接受 unary-expression 参数时无需使用括号,而且在使用括号和函数调用时行为也不同。

考虑下面的例子:_Static_assert(sizeof(0)==4,"");,则以下内容成立:

_Static_assert(sizeof(0)==4,"");
int takeIntGive4(int X){ (void)X; return 4; }

#include <assert.h>
int main()
{
    assert(sizeof(0)["foobar"] == 1  && 1 == sizeof(char)); //if sizeof were more function-like you'd get 'a'
    assert(takeIntGive4(0)["foobar"] == 'a');
}

换句话说,即使在这个平台上sizeof(0) == takeIntGive4(0)成立,你也不能总是简单地用sizeof(0)替换takeIntGive4(0),因为sizeof的优先级比函数调用低,sizeof(0)["foobar"]将被解释为sizeof( (0)["foobar"] ),而不是像sizeof()是函数一样,解释为(sizeof(0))["foobar"]
您可以通过将其包装在宏中并加括号来使sizeof类似于函数:
```#define mySizeof(x) sizeof(x)```
#define SIZEOF(X) (sizeof(X))

请记住,sizeof还会返回整数常量表达式(除非使用可变长度数组(VLAs)),您可以在case标签、位域大小和数组大小中使用这些常量表达式,而函数调用表达式无法返回这些值。


2

sizeof是一种运算符,因为它内置于语言中。就像+<一样,它包含在语言语法中。由于这个原因,sizeof运算符可以在程序编译时进行评估,而用户定义的函数则不行。例如,我们可以定义一个函数宏,该宏返回(非变量长度)数组的长度:

#define LENGTH(array) (sizeof (array) / sizeof (array)[0])

长度表达式是在程序编译时计算的。在运行时,数组的长度不可用(除非将其存储在单独的变量中)。


1
在编译变长数组时,通常不会计算sizeof - Eric Postpischil
1
大多数算术和关系运算符的使用不能在编译时评估。 - John Bollinger
@EricPostpischil 感谢您提供的信息。我已经更新了答案。 - August Karlstrom
@JohnBollinger 的确,操作数必须是常量表达式。 - August Karlstrom

2

这是一个在编译时计算的运算符。

实际上,只有当 T 是类型而不是类型的实例时,它才需要函数式语法 sizeof(T)

因此,例如,如果您有一个变量 int x,则可以使用 sizeof x;但对于类型 int,必须使用 sizeof(int)


1
如果 sizeof 的操作数具有可变长度数组类型,则其为编译时常量(技术上:必须符合整数常量)仅在其操作数不具有可变长度数组类型时。 - Eric Postpischil

1

sizeof是一个运算符。它在C标准的第6.5.3p1节中列在一元运算符列表中:

6.5.3 Unary operators

Syntax

unary-expression:
  postfix-expression
  ++ unary-expression
  -- unary-expression
  unary-operator cast-expression
  sizeof unary-expression
  sizeof (type-name)
  _Alignof (type-name)

unary-operator: one of
  & * + - ~ !
如上所示,它有两种形式。第一种形式是sizeof后跟一个表达式。请注意,在这种形式中,不需要括号,不像函数调用那样需要括号。第二种形式是sizeof后跟括号中的类型名称。只有第二种形式需要括号,并且函数不能传递类型名称。
在第6.5.3.4节中,它被进一步称为运算符:
6.5.3.4 sizeof_Alignof运算符
...
2 sizeof运算符返回其操作数的大小(以字节为单位),其可以是表达式或带括号的类型名称。大小由操作数的类型确定。结果是一个整数。如果操作数的类型是可变长度数组类型,则对操作数进行评估;否则,不评估操作数,结果是一个整数常量。

0
sizeof是函数还是运算符?为什么我们说sizeof(variable)是运算符而不是函数?
除了其他人已经回答的内容,代码可以获取函数的地址,但不能获取sizeof的地址。就像无法获取=或*的地址一样。
size_t (*f1)() = strlen;
size_t (*f2)() = sizeof;
//                     ^ error: expected expression before ';' token

使用对象时,与函数调用不同,sizeof 不需要 ()

char array[42];
size_t n1 = sizeof array;
size_t n2 = strlen(array) + 1;
 

sizeof 可以用于 类型,但不能用于函数调用。

size_t sz1 = sizeof(double);
size_t sz2 = printf(double);
//                  ^ error: expected expression before 'double'

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