2

今天,我写了一些代码来测试 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的类型改为float,然后再次编译,当我运行它时,输出是:

sum=0.000000, i=0
sum=1.100000, i=1
sum=3.300000, i=2

这一次,输出正常,但是在第一次输出中,为什么 i 的变量总是相同的值 1,有人可以告诉我吗?

4

3 回答 3

6

没什么可看的。您通过将错误的类型传递给 来调用未定义的行为printf,因此程序的所有输出都是没有意义的。%f格式说明符需要一个类型的参数(double顺便说一下,在这种情况下float会自动提升为,所以也可以),但是你传递了一个类型的参数。doublefloatint

于 2013-04-02T02:40:58.557 回答
1

您必须了解 va_arg 是如何工作的。Printf 是一个接受未定义数量参数的函数。问题是这些参数没有输入。

当您指定 int、double 等时,编译器会根据参数分配不同数量的字节(以特定顺序)。因此,当您调用具有类型参数的函数时,该函数知道它应该如何读取这些字节。在这里它无法知道,因为它不是类型。所以 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=%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 值。

于 2013-04-02T02:53:18.330 回答
0

我认为答案是,在第一种情况下,打印的值根本不是i。传递两个参数printf,然后读取两个参数。传入的是两个ints,然后是一个doubleandint被读取。因为double首先从堆栈中读取,所以在int读取时它不是从i传递值的位置,因此是虚假值。很可能double覆盖了足够多的堆栈以包含传递int的 s。

当然,结果可能会有所不同,不确定。

于 2013-04-02T02:41:43.170 回答