sizeof is surprisingly difficult to parse in c

sizeof 在 C 语言中解析起来出奇地困难

sizeof is surprisingly difficult to parse in c 2026-08-02 (because of course it is, literally everything in c is surprisingly difficult to parse). 在 C 语言中,sizeof 的解析难度出奇地高(当然,这并不令人意外,毕竟 C 语言中几乎所有东西解析起来都出奇地困难)。

for those unaware, the operand of sizeof is either a unary expression, or a parenthesized type name. so the following are all valid: sizeof 67 sizeof(67) sizeof(int) sizeof (x).y 对于不了解的人,sizeof 的操作数要么是一个一元表达式,要么是一个括号括起来的类型名。因此,以下写法都是合法的:sizeof 67sizeof(67)sizeof(int)sizeof (x).y

note that only types need to be parenthesized; expressions don’t. 请注意,只有类型才需要加括号;表达式则不需要。

the naive way to parse this is to first check for an opening parenthesis, and if one is found, try to parse a type name. luckily, that only requires reading one additional token. if that fails, push the parenthesis back into the token stream, and parse an expression instead. 一种简单的解析方法是:首先检查是否有左括号,如果发现,就尝试解析为一个类型名。幸运的是,这只需要多读取一个标记(token)。如果解析失败,就将括号放回标记流中,转而解析为一个表达式。

there’s a problem with that approach though: compound literals exist: sizeof(int){0} (int){0} is an expression. this is valid C code! but it makes parsing much more difficult. 然而这种方法存在一个问题:复合字面量(compound literals)的存在。例如 sizeof(int){0},其中 (int){0} 是一个表达式。这是合法的 C 代码!但这使得解析变得困难得多。

you could just add a special case when parsing a type name, to check for a { token after the closing parenthesis, and if one is found, parse a compound literal instead. but that isn’t enough either, because the expression can be followed by any number of postfix operators: sizeof(T){}.x0 你可以在解析类型名时增加一个特殊情况:检查右括号后是否有 { 标记,如果有,则将其解析为复合字面量。但这还不够,因为表达式后面可能跟着任意数量的后缀运算符,例如:sizeof(T){}.x[0]()

so one approach is to expand that special case to parse any number of postfix operators after the compound literal. another approach is to write a function which tries to parse either a unary expression or a parenthesized type name, so no backtracking is required. 因此,一种方法是扩展上述特殊情况,以解析复合字面量之后任意数量的后缀运算符。另一种方法是编写一个函数,尝试直接解析一元表达式或带括号的类型名,从而无需回溯。

but you have to be careful with this approach. it’s tempting to combine parsing unary expressions and cast expressions into a single function, to save on backtracking. normally you can do that without any problems, but that doesn’t work here: sizeof(int)+1 that’s an addition expression, not the size of a cast expression. (everything here also applies to c2y’s newly introduced _Countof) 但这种方法必须非常小心。为了节省回溯,人们很容易倾向于将一元表达式和强制类型转换表达式的解析合并到一个函数中。通常情况下这样做没问题,但在这种情况下却行不通:sizeof(int)+1,这是一个加法表达式,而不是一个强制类型转换表达式的大小。(此处提到的所有内容同样适用于 C2y 新引入的 _Countof。)