问候,今天当我在C99标准中尝试C语言时,我遇到了一个我无法理解并需要专家帮助的问题。
守则:
#include <stdio.h>
int main(void)
{
int Fnum = 256; /* The First number to be printed out */
printf("The number %d in long long specifier is %lld\n" , Fnum , Fnum);
return 0;
}
问题:
1.)当我尝试运行此代码时,此代码提示我一条警告消息。
2.)但奇怪的是,当我尝试将说明符%lld
更改为%hd
或%ld
时,
执行过程中没有显示警告信息,控制台上打印的值是正确的数字 256 ,即使我尝试使用,一切似乎也正常
%u
,%hu
以及%lu
。简而言之,只有当我使用long long说明符的变体时,才会发出警告信息和错误的数字打印。
3.)为什么会发生这种情况?我认为long long的内存大小足以容纳值 256 ,但为什么它不能用于打印出适当的值?
警告消息:(对于上述源代码)
C:\Users\Sam\Documents\Pelles C Projects\Test1\Test.c(7): warning #2234: Argument 3 to 'printf' does not match the format string; expected 'long long int' but found 'int'.
感谢您花时间阅读我的问题。上帝保佑。
答案 0 :(得分:6)
您将Fnum
变量传递给printf,其类型为int
,但它期待long long
。这与长长的 是否是否保持256无关,只是您选择的变量是int
类型。
如果你只想打印256,你可以获得一个输入unsigned long long
的常量,如下所示:
printf("The number %d in long long specifier is %lld\n" ,256 , 256ULL);
或演员:
printf("The number %d in long long specifier is %lld\n" , Fnum , (long long int)Fnum);
答案 1 :(得分:3)
这里有三件事。
printf
采用可变数量的参数。这意味着编译器不知道参数(超出格式字符串)应该是什么类型。所以它无法将它们转换为合适的类型。int
的整数类型会“提升”为int
。int
和long
的大小相同,即使指针是64位宽(这是微软对C89的故意违反 - 他们实际上强制要求在C99中更改标准它“好的”)。所有这一切的结果是:由于您在参数列表中使用了int
,因此不允许编译器将long long
转换为%lld
。 (允许警告您忘记了演员,因为警告超出标准行为。)因此,%lld
,您的程序无效。但是如果您使用任何其他大小说明符,printf
最终会查找与int
大小相同的参数,并且它可以正常工作。
答案 2 :(得分:1)
当处理可变参数函数时,调用者和被调用者需要某种方式来同意变量参数的类型。对于printf,这是通过格式字符串完成的。 GCC足够聪明,可以读取格式字符串本身,并确定printf是否会以与实际提供的方式相同的方式解释参数。
在某些情况下,您可以使用稍微不同类型的参数。例如,如果你传递一个short,那么它会被隐式转换为int。当sizeof(int)== sizeof(long int)时,也没有区别。但是sizeof(int)!= sizeof(long long int)所以参数在这种情况下无法匹配格式字符串。
答案 3 :(得分:1)
这是由于varargs在C中的工作方式。与普通函数不同,printf()
可以使用任意数量的参数。程序员可以通过提供正确的格式字符串来告诉printf()
期望什么。
在内部,printf()
使用格式说明符来访问与输入参数对应的原始内存。如果指定%lld
,它将尝试访问64位内存块(在Windows上)并将其找到的内容解释为long long int
。但是,您只提供了一个32位参数,因此结果将是未定义的(它会将您的32位int
与堆栈中接下来出现的随机垃圾组合在一起。)