程序使用printf输出的结果奇怪,无法理解。

8
我在处理一些面试问题时发现了这段代码。
#include<stdio.h>
int main()
{
 short int a=5;

 printf("%d"+1,a);    //does not give compiler error 

 return 0;
}

它会打印出以下内容:
d

我无法理解printf函数在这里的工作原理。


2
https://dev59.com/83RC5IYBdhLWcg3wMd9S#381554 应该能够澄清事情。 - DCoder
它会发出警告。我想printf()只想要第一个参数,也就是+1 - Haris
1
这里 printf("%d"+1,a); 相当于 printf("d"); - ani627
printf("%%%%")会打印什么内容,以及如何实现? - user3126632
这将打印 %%。要打印一个 %,你需要在 printf 中使用两个 %% - Spikatrix
显示剩余3条评论
4个回答

16

让我们看一下printf()调用的第一个参数。

"%d" + 1

这指的是以下代码中ptr所指的同一件事情。

char *ptr = "%d";
ptr = ptr + 1;

那么,什么是指针的增量?这意味着我们将指针向前移动sizeof(*ptr) * 1个字节。

因此,在内存中我们有:

%d\0
^^
||
|This is where ("%d" + 1) points to.
This is where ("%d") points to.

所以,您的代码在功能上与执行以下操作基本相同:

short int a = 5;
printf("d", a);

执行后会评估并忽略额外的函数参数,并打印出 d


还有一件事:您的代码非常接近导致未定义行为。 printf("%d",a) 使用了错误的格式字符串。一个 short int 的正确格式字符串是 "%hd"

您可以在此处找到完整的格式字符串表。


7
使用%d打印short类型没问题,它们会自动转换为int类型。 - mafso
printf 中的 % 运算符表示编译器要执行什么操作? - user3126632
这段代码会发生什么事情? printf("%",a); - user3126632
@user3126632:这不是编译器指令。 printf 是一个简单的函数,它扫描其第一个参数,即格式字符串,以查找它识别的序列。请阅读 man printf - Jongware
2
将指针递增意味着将其向前移动1个位置,而不是sizeof(*ptr)*1。后者表示的是字节数。 - M.M
@MattMcNabb:我的意思是它将sizeof(*ptr) * 1字节向前移动。修正为:s/positions/bytes。如果你认为有更好的措辞,也可以自由编辑。 - Bill Lynch

7

"%d" + 1 进行指针运算时,编译器会将其视为"d",因此结果会不正确。

printf("%d"+1,a); 

成为:

printf("d", a); 

你可以看到为什么在你的编译器中输出了d
正如@sharth在评论中指出的那样,这里的额外参数a会被评估并丢弃。

8
传递额外的参数并不是未定义行为。只有当你传递太少的参数时才是未定义的。https://dev59.com/onA65IYBdhLWcg3w4C6j#3579752 - Bill Lynch
@sharth 我不知道这个。通过回答问题学到新东西真是太好了 ;) - Yu Hao

2

这是基于@DCoder评论的答案。 "%d"是指向两个字符数组%d的第一个字符的指针。 将其增加一会得到指向d的指针。 现在有第二个参数并不重要,因为表达式"%d"+1的结果只是字符d。 如果您尝试添加0,则输出结果为5,这是预期的。 如果您尝试添加2,则没有输出,因为只有""被传递给printf


2
如果您尝试添加2,则格式为""。如果您尝试添加超过2个,则行为未定义。 - chux - Reinstate Monica

1
在这种情况下,printf("%d"+1,a); = printf("d",a)
您正在指定printf从+1位置打印,这是"d",因此printf将只在屏幕上打印d

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