C中自动类型转换有哪些限制?它在变量参数中起作用吗?
据我所知,在 C 中,当我尝试将小数据类型存储在较大的数据类型中时,会发生自动类型转换或类型提升。例如,int 被提升为 float 或 double。 但在下面的代码中,我得到了垃圾值:
#include <stdio.h>
#include<stdarg.h>
double average(int num,...)
{
va_list a_list;
double sum=0.0;
va_start(a_list,num);
for(int i=0;i<num;i++)
sum+=va_arg(a_list,double);
va_end(a_list);
return sum/num;
}
int main()
{
printf("%.2lf\n",average(5,4.0,7,8,9,10));
printf("%.2lf\n",(4.0+7+8+9+10)/5);
return 0;
}
第一个 printf 函数没有给出正确的输出,而第二个给出了。
To the best of my knowledge, in C auto type conversion or type promotion takes place when I try to store small data type in larger data type. For example, int is promoted to float or double.
But in the code below, I am getting garbage value:
#include <stdio.h>
#include<stdarg.h>
double average(int num,...)
{
va_list a_list;
double sum=0.0;
va_start(a_list,num);
for(int i=0;i<num;i++)
sum+=va_arg(a_list,double);
va_end(a_list);
return sum/num;
}
int main()
{
printf("%.2lf\n",average(5,4.0,7,8,9,10));
printf("%.2lf\n",(4.0+7+8+9+10)/5);
return 0;
}
The first printf function does not give correct output, whereas the second one gives.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
当为函数参数的
...
部分传递参数时,仅执行默认参数提升。其中包括整数提升以及将float
转换为double
。它们不会将整数类型转换为浮点类型。将参数传递给具有声明的参数类型的函数时发生的转换依赖于在编译程序时提前了解类型,以便可以以指定的方式传递参数。每个计算平台都有一些传递参数的规则,称为应用程序二进制接口 [ABI]。 ABI 的一个共同特征是整数和指针参数在处理器的通用寄存器中(或在堆栈上)传递,而浮点参数在浮点寄存器中传递。
当存在可变参数列表并且使用
va_arg
时,被调用函数在程序执行期间请求参数。当被调用函数通过va_arg
请求整数值时,va_arg
会尝试从传递整数参数的位置获取该值。当被调用函数请求浮点值时,va_arg
尝试从要传递浮点参数的位置获取该值。被调用的函数无法知道您传递的是整数参数还是浮点参数,因此它无法指示 va_arg 从您传递参数的位置而不是从哪里获取值它期望参数是。您必须传递正确类型的参数。When arguments are passed for the
...
portion of a function’s parameters, only the default argument promotions are performed. These include the integer promotions and convertingfloat
todouble
. They do not convert integer types to floating-point types.The conversions that occur in passing arguments to functions with declared parameter types rely on knowing the types in advance, when the program is compiled, so that the arguments can be passed in a specified way. Each computing platform has some rules for passing arguments, called the application binary interface [ABI]. A common characteristic of ABIs is that integer and pointer arguments are passed in general registers of the processor (or on a stack), while floating-point arguments are passed in floating-point registers.
When there is a variable argument list and
va_arg
is used, the called function is requesting arguments during program execution. When the called function requests an integer value withva_arg
,va_arg
attempts to get it from where an integer argument would be passed. When the called function requests a floating-point value,va_arg
attempts to get it from where a floating-point argument would be passed. The called function has no way of knowing whether you passed an integer argument or a floating-point argument, so it has no way of directingva_arg
to fetch the value from where you passed the argument rather than from where it expects the argument to be. You must pass the correct type of arguments.va_list 不存在类型安全性,因此如果您在变量参数列表中混合使用几种不同的类型,则需要以某种方式跟踪它们的类型。这就是
printf
对格式字符串所做的事情。可变参数函数的参数列表根据称为“默认参数提升”的奇怪规则进行提升(C17 6.5.2.2/6):
这意味着小整数类型会提升为
int
,但像5
这样已经是int
的常量不会提升,特别是不要浮点类型。因此,根据上面的引用,您的代码具有未定义的行为,因为该函数将int
参数视为double
。不建议将可变参数函数用于任何目的,它们几乎肯定是您遇到的任何问题的错误解决方案。请改用数组和/或结构体。
va_list
has non-existent type safety so if you mix several different types in the variable argument list, you need to keep track of their types somehow. That's whatprintf
does with the format string.The argument list of a variadic function is promoted according to an oddball rule called the default argument promotions (C17 6.5.2.2/6):
Meaning that small integer types get promoted to
int
, but constants like5
that are alreadyint
do not get promoted, particularly not to a floating point type. So your code has undefined behavior as per the above quote, since the function treatsint
arguments asdouble
.Variadic functions are not recommended to be used for any purpose, they are almost certainly the wrong solution to any problem you are having. Use arrays and/or structs instead.