我在c中练习编程,但我遇到了一个我似乎无法弄清楚的问题。我有一个printf
语句,其中包含两个不同int
值的标记。无论第一个int
是什么,它都会打印0,但第二个int
会正常打印。这是代码:
#include <stdio.h>
#include <stdlib.h>
int a, temp;
int toBinary();
int toDecimal();
int main()
{
char c;
for(;;)
{
scanf("%d",&a);
scanf(" %c",&c);
switch(c)
{
case 'a' :
printf("%d converted to binary: %d\n",a,toBinary());
break;
case 'b' :
printf("%d converted to decimal: %d\n",a,toDecimal());
break;
case 'c' :
printf("EXIT\n");
return 0;
break;
default :
printf("ERROR c value: %c\n",c);
return 0;
}
}
}
int toBinary()
{
if (a == 0)
return 0;
else
{
temp = a;
a /= 2;
return (temp % 2 + 10 * toBinary());
}
}
int toDecimal()
{
int res=0, base = 1, rem;
while (a > 0)
{
rem = a % 10;
res = res + rem * base;
a /= 10;
base *= 2;
}
return res;
}
问题是前两种情况中的printf
语句忽略int a
的实际值,但它通常用于两个函数的值。我不确定错误是什么,因为在a
声明中scanf
之前已经给出了值,而我在文本中使用了正确的标记。
答案 0 :(得分:5)
由于未指定参数评估的顺序,因此这是未定义的行为。
最简单的解决方法是将a
的副本保存在另一个变量中,然后打印出来。
int a_copy = a;
printf("%d converted to binary: %d\n",a_copy,toBinary());
但如果函数首先不使用全局变量会更好。
int toBinary(int a)
{
if (a == 0)
return 0;
else
{
return (a % 2 + 10 * toBinary(a / 2));
}
}
然后你会这样做:
printf("%d converted to binary %d"\n, a, toBinary(a));
答案 1 :(得分:1)
如果在https://<yourname>.ocpu.io/
或a
中修改了toBinary()
,它就是一个UB 。
未指定一个函数调用中的参数评估顺序。一些编译器评估它们L-> R(如GCC),其他一些编译器R-> L(如VC)。
试试这个,你就会发现它:
toDecimal()
答案 2 :(得分:0)
由于语句a
的存在,函数toBinary()
中0
的值减少到a /= 2;
,并且会以递归方式执行。
因此,您的printf语句会打印0
以获取a
的值。
正如@Barmar建议的那样,在函数中使用局部变量而不是全局变量是一种很好的编码实践。