为什么此代码打印为0?

时间:2018-08-15 14:47:46

标签: c

void main()
{
    clrscr();
    float f = 3.3;

    /* In printf() I intentionaly put %d format specifier to see
       what type of output I may get */
    printf("value of variable a is: %d", f);
    getch();
}

5 个答案:

答案 0 :(得分:7)

实际上,%d告诉printf在某个位置查找整数参数。但是您传递了一个float参数,该参数放在另一个位置。 C标准未指定执行此操作时将发生的情况。在这种情况下,printf查找整数参数的位置可能为零,因此它显示为“ 0”。在其他情况下,可能会发生一些不同的事情。

答案 1 :(得分:2)

printf使用无效的格式说明符将调用undefined behaviorC standard的第7.21.6.1p9节对此进行了指定:

  

如果转换规范无效,则行为为   282)如果任何参数不是正确的类型   相应的转换规范,其行为是不确定的。

这意味着您无法可靠地预测程序的输出。例如,我系统上的相同代码将-1554224520打印为该值。

关于最有可能发生的事情,%d格式说明符正在寻找int作为参数。假设在堆栈上传递了int,并且int的长度为4个字节,则printf函数将在堆栈的后4个字节中查找给定的值。许多实现都没有在堆栈上传递浮点值,而是在寄存器中传递浮点值,因此它可以看到任何垃圾值。即使在堆栈上传递了floatfloatint的表示形式也非常不同,因此将float的字节打印为int可能不会给您相同的价值。

答案 2 :(得分:0)

让我们看一下另一个例子。假设我写

#include <string.h>

char buf[10];
float f = 3.3;
memset(buf, 'x', f);

memset的第三个参数应该是整数(实际上是类型为size_t的值),它告诉memset but的多少个字符要设置为{{ 1}}。但是我改为传递了一个'x'值。怎么了?好的,编译器知道第三个参数应该是整数,因此它会自动执行适当的转换,并且代码最终会设置{{1的前三个(三点)字符}}到float

(重要的是,编译器知道buf的第三个参数应该是整数的方式基于'x'原型函数声明标头memset的内容。)

现在,当您打电话

memset

您可能会认为同一件事也会发生。您通过了<string.h>,但是printf("value of variable f is: %d", f); 期望有float,所以会发生自动转换,对吧?

错误。让我再说一遍:错误

也许令人惊讶的事实是%d是不同的。 int很特殊。编译器不一定知道传递给printf的参数的正确类型,因为它取决于掩埋在格式字符串中的printf指定符的详细信息。因此,不会自动转换为正确的类型。确保您实际传递的参数类型完全适合格式说明符,这是您的工作。如果它们不匹配,则编译器会 not 自动执行相应的转换。如果它们不匹配,那将导致您发疯,错误的结果。

printf的原型函数声明是什么样的?从字面上看起来是这样的:%。这三个点printf表示一个可变长度参数列表< / em>或“ varargs”,它们告诉编译器它不知道还有多少个参数,或者它们的类型应该是什么。因此,编译器执行一些基本的转换-例如上转换类型{{1 }}和extern int printf(const char *, ...);...,以及charshort int,然后将其保留。)

我说过:“编译器不一定知道传递给int的参数的正确类型是什么”,但是如今,好的编译器会付出更多努力并尝试找出答案,如果可以的话。他们仍然不会执行自动转换(根据语言规则,他们实际上是不允许这样做的),但是它们至少可以警告您。例如,我在两种不同的编译器下尝试过您的代码。双方都说了float。如果您的编译器没有给您这样的警告,建议您查明是否可以启用这些警告,或者考虑切换到更好的编译器。

答案 3 :(得分:-4)

尝试

printf("... %f",f); 

这就是您打印浮动数字的方式。 也许您只想打印 f 的x位数字,例如:

printf("... %.3f" f);

这将在点后用3位数字打印您的浮点数。 请仔细阅读以下列表:

%c-字符

%d或%i-有符号十进制整数

%e-使用e字符的科学计数法(尾数/指数)

%E-使用E字符的科学计数法(尾数/指数)

%f-十进制浮点数

%g-使用%e或%f的较短者

%G-使用%E或%f中的较短者

%o-八进制签名

%s-字符串

%u-无符号十进制整数

%x-无符号十六进制整数

%X-无符号十六进制整数(大写字母)

%p-指针地址

%n-什么都没打印

答案 4 :(得分:-4)

代码正在打印0,因为您使用的是格式标记%d,它表示带符号的十进制整数(http://devdocs.io)。

请您尝试

void main() {

   clrscr();
   float f=3.3;

   /* In printf() I intentionaly put %d format specifier to see what type of output I may get */

   printf("value of variable a is: %f",f); 
   getch();

}