输出原因

4
#include<stdio.h>
int main(void)
{
 int a=5;
 printf("%d"+1,a);
}

输出:d。 我不明白输出为什么是 d?
6个回答

24
您将 printf 的第一个参数设为 "%d"+1,实际上 "%d" 被视为指向存储有 %d 的内存位置的 const char *。与任何指针一样,如果您将其增加1,则结果将指向以下元素,在这种情况下,将是 d

a 没有被使用,但这不应该是一个问题,因为通常(我不知道是否标准化 编辑:是的,可以看底部),可变参数函数的栈清理责任由调用者承担(至少cdecl 使用此方式),但这可能是UB,我不确定*)。

您可以通过以下方式更轻松地查看:

#include<stdio.h>
int main(void)
{
    int a=5;
    const char * str="%d";
    printf(str + 1, a);
}

 

str ---------+
             |
             V
          +----+----+----+
          |  % |  d | \0 |
          +----+----+----+

str + 1 ----------+
                  |
                  V
          +----+----+----+
          |  % |  d | \0 |
          +----+----+----+

因此,("%d"+1) (即 "d")被解释为格式化字符串,printf 没有找到任何 %,会直接将其打印出来。如果你想要打印 a 加 1 的值,应该这样做:

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


编辑: * 好的,这不是未定义行为(UB),至少对于C99标准(§7.19.6.1.2),在fprintf中拥有未使用的参数是可以的:

如果格式已用尽而仍有参数剩余,则评估过多的参数(始终如此),但是其它方面会被忽略。

printf也定义为具有相同的行为,位于§7.19.6.3.2中

printf函数等效于在参数之前插入stdout参数的fprintf函数。


谢谢 :) - Matteo Italia
将未使用的值传递给printf函数在标准中是不会出问题的。当然,实际的实现可以有所不同,但我还没有看到除了你描述的之外的情况。 - Roger Pate
"至少对于C99标准而言" -- 这是其他的。如果标准要求varargs函数按顺序消耗所有参数才能定义行为,那将是可怕的。 - Jim Balter
@JimBalter:我写这篇答案已经有一段时间了,但我想我当时写那个是因为我没有C89标准(至于C11,它还不存在)。请随意添加其他版本标准的相关引用。 - Matteo Italia

12

字符串字面量是指针。将指向"%d"的指针向前移动1个位置会得到"d"。参数被丢弃。


2

你应该使用printf("%d", a+1)"%d" + 1 是一个指向{'%','d','\0'}字符数组中的"d"的指针。


1
假设你有:

char x[] = "%d";

你期望什么

printf(x + 1, a);

打印?

提示:t.c:5: 警告:格式的参数过多。


1

因为+1。如果你想要增加a,请使用:printf("%d", a + 1);


0
"%d" 是字符串常量,它将被存储在内存中的 char[] 中。在运行时,“%d”返回 char[] 的起始位置。通过将字符数组指针增加一,可以指向下一个字符。因此,仅传递 "d" 给 printf 函数。所以输出是 "d"。

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