今天,我编写了一些代码来测试unsigned int。
#include <stdio.h>
int sum_element(float ele[], unsigned int len);
int main(void){
float ele[] = {1.1,2.2,3.3};
float sum = sum_element(ele,3);
printf("sum is %f\n",sum);
return 0;
}
int sum_element(float ele[], unsigned int len){
int sum=0.0; //mistake,should be : float sum = 0.0
int i=0;
for(i=0;i<= len-1;i++){
printf("sum=%f, i=%d\n",sum,i);
sum += ele[i];
}
return sum;
}
在这个例子中,我有一个错误,变量sum的类型,应该是float,但我写int,编译命令:
gcc test.c -o test
我运行此代码
./test
函数sum_element的输出是:
sum=0.000000, i=1
sum=0.000000, i=1
sum=0.000000, i=1
然后我发现了错误,我将总和的类型更改为浮动,然后再次编译, 当我运行它时,输出是:
sum=0.000000, i=0
sum=1.100000, i=1
sum=3.300000, i=2
这次,输出像正常一样,但在第一次输出时,为什么i的变量始终是1的相同值,有人可以告诉我吗?
答案 0 :(得分:6)
没什么可看的。您通过将错误的类型传递给printf
来调用未定义的行为,因此程序的所有输出都是无意义的。 %f
格式说明符需要double
类型的参数(顺便说一下,float
会在此上下文中自动提升为double
,因此float
可以正常也是),但你传递了int
类型的参数。
答案 1 :(得分:1)
您必须了解va_arg的工作原理。 Printf是一个接受未定义数量的参数的函数。问题是这些参数没有输入。
当指定int,double,ect时......编译器根据参数分配不同的字节数(按特定顺序)。因此,当您调用具有类型参数的函数时,该函数知道它应该如何读取这些字节。 这里它不知道因为它不是类型。所以printf函数会相信你给它的东西。如果你要求例如4个字节,当你的实际值是8个字节时,该函数将读取前4个字节,认为它是你要求的值。但是,您尝试匹配的下一个值将从接下来的4个字节开始。你会给你垃圾。
你可以尝试做2个printf,你会发现i的值实际上是好的。只有阅读它的方式是错误的。
int sum_element(float ele[], unsigned int len){
int sum=0.0; //mistake,should be : float sum = 0.0
int i=0;
for(i=0;i<= len-1;i++){
printf("sum=%f\n",sum);
printf("i=%d\n",i);
}
return sum;
}
希望这可以提供帮助。
编辑:
也许一个例子更容易理解。试试这个功能:
int sum_element(float ele[], unsigned int len){
int sum=24222.55455555; //mistake,should be : float sum = 0.0
char c = 0 ;
for(i=0;i<= len-1;i++){
printf("sum=%f, n= %d n2 = %d\n",sum,i,c);
}
return sum;
}
你应该为n2获得一个有趣的值。
答案 2 :(得分:0)
我认为答案是,在第一种情况下,打印的值根本不是i
的值。两个参数传递给printf
,然后读取两个参数。传入的内容有两个int
s,然后会读取double
和int
。因为首先从堆栈读取double
,所以当读取int
时,它不是从i
的值传递的位置,因此是伪造的值。最有可能的是double
覆盖了足够的堆栈以包含传递的int
。
当然,结果可能会有所不同,未定义。