为什么我得到这个意外的printf输出?

时间:2017-06-23 14:46:15

标签: c

我试图理解printf在这些情况下是如何运作的:(这是测试中的一个额外问题)

案例1:

int d=1;
printf("%d",(int)"printf("%d);

输出:0

案例2 :(最后没有%d

int d=1;
printf("%d",(int)"printf(");

输出:15554368

这是如何工作的?为什么%d会让它与众不同?

3 个答案:

答案 0 :(得分:3)

让我们从第二个例子开始:

int d=1;
printf("%d",(int)"printf(");

"printf("这里是一个字符串常量,只包含C函数的名称以试图混淆你。字符串常量的类型为char *,它是指向第一个字符的指针。 (int)将指针转换为整数。虽然这是实现定义,但您将获得某些值,该值与实际存储字符串"printf("的地址相关。

所以你在这里打印一个数字,恰好是转换为int的指针的结果。

继续前进:

int d=1;
printf("%d",(int)"printf(" % d);

只有一个更改,我添加了空格以显示:您从指针转换获得的intd ,所以结果是整数除以d的余数。由于d是1,所以不会有任何余数,任何数字都可以除以1而没有余数。因此,结果为0

答案 1 :(得分:3)

这个奖金问题是一个棘手的问题:

printf("%d",(int)"printf("%d);被解析为

printf(
       "%d",
       ((int)"printf(") % d
      );

字符串"printf("的地址转换为int,并计算模数运算。自d = 1起,模数始终为0。因此printf输出0

第二个调用只是打印转换为int的字符串的地址,这个地址会因环境而异,甚至可能因运行而异(在我的Mac上运行)...

事实上,转换甚至可能失败并触发特定于实现的行为。因此,在两种情况下,答案都应该是实现定义的行为。

另一个问题应该是:

int d=1;
printf("%d",(int)printf("%d", d));

哪个产生11。你能解释一下原因吗?

请注意,即使是最后一个问题也很棘手:在没有正确原型的情况下调用printf,例如,如果未包含<stdio.h>,则会有未定义的行为。

答案 2 :(得分:2)

第二个%d不是printf()说明符,它是%模除法运算符和int变量d价值1,有什么区别?它们根本不相同。

第二个问题是,您正在投射指向int的指针,该指针没有明确定义。