问题描述
为什么我们说 sizeof(variable)
是一个运算符,而不是一个函数?
它看起来像一个函数调用,当我在思考操作符的含义时,它看起来像 +
或 -
或 *
等等
解决方法
它是一个运算符,因为它不像函数那样接受参数。它在语法级别运行。
f(int)
不是有效的函数调用,但 sizeof(int)
是 sizeof
的有效用法。
它还可以对变量或类型进行操作,它的设计非常灵活,这是运算符可以执行的操作,因为它已深入到 C 语法中。
更多详情can be found here。
,它是一个运算符,不需要使用方括号,除了“当操作数是类型名称时,它必须用括号括起来”。这是一个语法限制,但不应与函数调用混淆。
请参阅下面来自 GNU Python Tutorial: Web Scraping with BeautifulSoup and Requests 的最后一个示例:
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 12
或 sizeof a
没问题。
它是一个运算符,因为它内置于语言中。就像 +
或 <
一样,它包含在语言语法中。因此,与用户定义的函数不同,可以在编译程序时评估 sizeof
运算符。例如,我们可以定义一个函数宏,它返回一个(非可变长度)数组的长度:
#define LENGTH(array) (sizeof (array) / sizeof (array)[0])
长度表达式是在程序编译时计算的。在运行时,数组的长度不可用(除非您将其存储在单独的变量中)。
,这是一个在编译时计算的运算符。
实际上,当 sizeof(T)
是类型而不是类型的实例时,它只需要类似函数的语法 T
。
因此,例如,如果您有一个变量 int x
,则 sizeof x
是允许的;但 sizeof(int)
类型需要 int
。
如语法所示:
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,"");
#include <assert.h>
int takeIntGive4(int X){ (void)X; return 4; }
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');
}
您可以通过将其包装在宏中来使其更像函数:
#define SIZEOF(X) (sizeof(X))
但 sizeof
还额外返回整数常量表达式(与可变长度数组 (VLA) 一起使用时除外),您可以在 case
标签、位域大小和数组大小以及哪些函数中使用它调用表达式无法返回。
sizeof
是一个运算符。它列在 C standard 的 6.5.3p1 节中的一元运算符列表中:
6.5.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
& * + - ~ !
如上图所示,它有两种形式。第一种形式是 sizeof
后跟一个表达式。请注意,在这种形式中不需要括号,这与它们所在的函数调用不同。第二种形式是 sizeof
后跟括号中的类型名称。只有第二种形式需要括号,函数不能传递类型名。
在第 6.5.3.4 节中进一步称为运算符:
6.5.3.4 sizeof
和 _Alignof
运算符
...
2 sizeof
运算符产生其操作数的大小(以字节为单位),它可以是表达式或括号内的类型名称。大小由操作数的类型决定。结果是一个整数。如果操作数的类型是变长数组类型,则对操作数求值;否则,不计算操作数,结果为整数常量
sizeof 是函数还是运算符?
为什么我们说 sizeof(variable) is operator not function?
除了其他已经回答的,代码可以取函数的地址,但不能取sizeof
的地址。很像 can 不能取 =
或 *
的地址。
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'