在C语言中计算整数表达式的大小

7

对于使用 Xcode 编译 C(gnu11)的经验,我有些半惊讶。

#include <stdio.h>
int main(int argc,char**argv)
{
    short s = 1;
    printf( "%zd %zd %zd\n", sizeof(s), sizeof(s*s), sizeof(s?s:s));
    return 0;
}

生成输出

2 4 4

我很期待,
2 2 2

或可能

2 4 2

为什么会这样呢?

3个回答

8

我从K&R中回想起任何小于int的整数表达式都会被提升为int。 我在标准(C89)中找到了这一点:

3.2.1.1 字符和整数

char、short int或int位域,它们的有符号或无符号变体或具有枚举类型的对象都可以在表达式中使用,无论何时都可以使用 int 或 unsigned int。如果int可以表示原始类型的所有值,则将该值转换为int;

令人惊讶的是s?s:s,因为我找到的所有参考资料都说结果类型是lvalue,但这只适用于C ++。 C将其视为rvalue。 然后,C ++的输出如下所示:

2 4 2

即使表达式是rvalue,在C和C ++之间存在意外差异。

2
C和C++之间的另一个微妙差异在使用sizeof运算符时可见:在C中,printf("%zd\n", sizeof('s'));可能会打印出4,但在C++中始终为1 - chqrlie

6
这是因为后两个sizeof操作数包含运算符。在C语言中,比int窄的类型在执行操作之前会被提升为int。因此,s * s是一个int乘以一个int,得到一个int
同样地,short ? short : short也会被提升为int ? int : int

在我找到的规范中,它被称为条件表达式而不是三元运算符。即使对于位域,','运算符也不会提升并且像我期望的那样工作:?。看来这是你必须知道的其中一件事情。 - Tony Lee

4
根据C11§6.5.15/5:

如果第二个和第三个操作数都是算术类型,那么将这两个操作数应用于通常的算术转换所确定的结果类型就是结果的类型。[...]

在您的情况下,结果等于sizeof(int),因为“通常的算术转换”会将short提升为int。与sizeof(s*s)相同。

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