我有一些与此代码相关的问题。printf的参数是const char*
和...
(可变参数列表)的类型。
1)为什么程序的输出是d
而不是127
?
2)是不是+1
会被转换成字符串并传递给类型为const char*
的参数变量?
#include<stdio.h>
int main()
{
printf("%d"+1 , 127); //how this will get executed?
return 0;
}
输出:
d
我有一些与此代码相关的问题。printf的参数是const char*
和...
(可变参数列表)的类型。
1)为什么程序的输出是d
而不是127
?
2)是不是+1
会被转换成字符串并传递给类型为const char*
的参数变量?
#include<stdio.h>
int main()
{
printf("%d"+1 , 127); //how this will get executed?
return 0;
}
输出:
d
第一个参数是指向 char
的指针。
字面量 "%d"
是指向 '%'
的指针,隐含后面跟着 'd'
和 '\0'
。它是指向 char
的指针,因为这是字符串字面量在C中的表示方式:以字符序列结尾为'\0'
; 作为参数等表示时,使用char
指针表示。
但是,根据指针算术,"%d"+1
是指向 'd'
,后面跟着 '\0'
的指针。
两个都以零结尾,适合作为 printf 的参数。
所以输出与…相同。
printf("d", ignored);
因为"d"
告诉printf不要期望任何东西,所以它会被忽略,127会变成"ignored"。这是因为它没有任何特殊字符序列,比如"%someletter"。因此,它不期望、也不寻找任何内容,并且除了正常的字符串之外,不打印任何内容。
但需要注意的是,那些格式化字符串中没有涵盖的额外参数会在评估后被忽略。这一点很重要,因为评估的副作用(例如函数调用)实际上是会发生的。
有关详细信息,请参见:
http://en.cppreference.com/w/c/io/fprintf
printf("d", ...)
与其后面的任何内容都没有关系。 - Eugene Sh."%d"
这样的字符串常量是一个数组表达式(因为字符串被存储为数组)。在大多数情况下,数组表达式会被转换为指向该数组第一个元素的指针表达式。如果将指针加 1,则结果是指向下一个对象的指针(在此情况下为字符串的第二个字符)。因此,printf
将字符串 "d"
视为第一个参数。由于 "d"
中没有任何转换说明符,printf
不会检查任何其他参数-参数 127
将被忽略。 - John Bode让我尝试帮助并补充@Yunnosch的回答,您可以做以下操作:
char *str = "%d";
printf (str, 127);
127
str
存储在内存中像这样(这只是一个例子,在实际生活中地址会像 0xabcdef12345678):address | memory
--------+--------------
0 | %
1 | d
3 | \0
str
指向地址0
(或等效于您的系统),该地址保存%
,printf()
获取该地址并从那里开始读取,一直读取到NULL字符'\0'。现在每次看到%
时,它都会查找下一个字符d
、c
、x
等,并从参数列表中读取下一个参数。如果您提供了d
,它将输出十进制数,如果您提供了c
,它将打印字符,x
用于十六进制,还有许多其他用途。因此,printf()
将读取所有字符,并使用适当的参数替换%<place holder>
,直到它遇到NULL字符\0
,但它将从提供的地址开始。printf("%d"+1, 127);
等同于:
char *str = "%d";
printf (str + 1, 127); // printf receives address of character `d` as starting point
char *str = "%d";
char *str1 = str+1; // increment the address of string by one
printf (str1, 127)
在这两种情况下,它都会接收d
的地址,并从那里读取,直到遇到\0
。
如果你执行以下操作:
printf ("%d" + 2, 127);
这与以下内容相同:
char *str = "%d";
printf (str + 2, 127);
如果采用printf()
,它不会有任何输出,因为printf()
将获取\0
的地址。正如@Yunnosh所说,127
将被忽略。
因此,+1
和+2
并没有被转换为字符串,它们被添加到了字符串的地址上。
希望这可以帮到你,我想我回答了你的两个问题。