今天,我写了一些代码来测试无符号的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 %fn",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=%dn",sum,i);
sum += ele[i];
}
return sum;
}
在这个例子中,我有一个错误,变量 sum 的类型应该是浮点数,但我写了 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,有人可以告诉我吗?
没什么可看的。你通过将错误的类型传递给printf
来调用未定义的行为,因此程序的所有输出都是没有意义的。%f
格式说明符需要一个类型 double
的参数(顺便说一下,在这种情况下,float
会自动提升为 double
,所以float
也可以(,但你给它传递了一个类型 int
的参数。
了解va_arg是如何工作的。Printf 是一个接受未定义数量的参数的函数。问题是这些参数不是键入的。
当您指定整数、双精度等时...编译器根据参数分配不同的字节数(按特定顺序(。因此,当您调用具有类型参数的函数时,该函数知道它应该如何读取这些字节。在这里它无法知道,因为它不是类型。所以printf函数会相信你给它的东西。例如,当您的实际值为 8 字节时,如果您要求 4 个字节,则该函数将读取前 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=%fn",sum);
printf("i=%dn",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 = %dn",sum,i,c);
}
return sum;
}
你应该得到一个有趣的 n2 值。
我认为答案是,在第一种情况下,打印的值根本不是i
的值。两个参数传递给printf
然后读取两个关闭。传入的是两个int
,然后读出一个double
和int
。由于首先从堆栈中读取double
,因此在读取int
时,它不是从传递i
值的位置传递的,因此是虚假值。最有可能的是,double
覆盖了足够的堆栈,以包括传递的int
。
当然,结果可能会有所不同,无法定义。