C int数据类型及其变体

时间:2011-04-06 18:53:05

标签: c variables types int

问候,今天当我在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'.

感谢您花时间阅读我的问题。上帝保佑。

4 个答案:

答案 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)

这里有三件事。

  1. printf采用可变数量的参数。这意味着编译器不知道参数(超出格式字符串)应该是什么类型。所以它无法将它们转换为合适的类型。
  2. 但是,由于历史原因,在可变参数列表中传递时,小于int的整数类型会“提升”为int
  3. 您似乎在使用Windows。在Windows上,intlong的大小相同,即使指针是64位宽(这是微软对C89的故意违反 - 他们实际上强制要求在C99中更改标准它“好的”)。
  4. 所有这一切的结果是:由于您在参数列表中使用了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与堆栈中接下来出现的随机垃圾组合在一起。)