下面是在dev c++ windows中编译的代码:

#include <stdio.h>

int main() {
    int x = 5;
    printf("%d and ", sizeof(x++)); // note 1
    printf("%d\n", x); // note 2
    return 0;
}

我期望在执行注释1后x为6。然而,输出结果是:

4 and 5

有人能解释一下为什么x在注释1之后没有增加吗?


当前回答

Sizeof()操作符只给出数据类型的大小,它不计算内部元素。

其他回答

在编译期间不能执行。所以++i/i++不会发生。sizeof(foo())也不会执行函数,而是返回正确的类型。

由于sizeof操作符的操作数没有被求值,你可以这样做:

int f(); //no definition, which means we cannot call it

int main(void) {
        printf("%d", sizeof(f()) );  //no linker error
        return 0;
}

在线演示:http://ideone.com/S8e2Y

也就是说,如果只在sizeof中使用函数f,则不需要定义它。这种技术主要用于c++模板元编程,因为即使在c++中,sizeof的操作数也不计算。

为什么会这样?它可以工作,因为sizeof操作符不操作值,而是操作表达式的类型。因此,当你编写sizeof(f())时,它对表达式f()的类型进行操作,而f()只是函数f的返回类型。返回类型总是相同的,无论函数实际执行时会返回什么值。

在c++中,你甚至可以这样做:

struct A
{
  A(); //no definition, which means we cannot create instance!
  int f(); //no definition, which means we cannot call it
};

int main() {
        std::cout << sizeof(A().f())<< std::endl;
        return 0;
}

然而,在sizeof中,我首先创建了A的实例,通过编写A(),然后调用实例上的函数f,通过编写A().f(),但这样的事情没有发生。

演示:http://ideone.com/egPMi

下面是另一个主题,它解释了sizeof的其他一些有趣的属性:

Sizeof取两个参数

Sizeof()操作符只给出数据类型的大小,它不计算内部元素。

这一行:

printf("%d and ", sizeof(x++)); // note 1

导致乌兰巴托。%d期望类型int而不是size_t。获得UB后,行为是未定义的,包括写入标准输出的字节。

如果你想通过将%d替换为%zu或将值转换为int来解决这个问题,但不是两者都用,你仍然不会增加x,但这是一个不同的问题,应该在不同的问题中问。

Sizeof是一个编译时内置操作符,不是一个函数。在不带括号的情况下,这一点变得非常明显:

(sizeof x)  //this also works