C中自动类型转换有哪些限制?它在变量参数中起作用吗?

发布于 2025-01-12 15:42:58 字数 534 浏览 0 评论 0原文

据我所知,在 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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

本王不退位尔等都是臣 2025-01-19 15:42:58

当为函数参数的 ... 部分传递参数时,仅执行默认参数提升。其中包括整数提升以及将 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 converting float to double. 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 with va_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 directing va_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.

蘑菇王子 2025-01-19 15:42:58

va_list 不存在类型安全性,因此如果您在变量参数列表中混合使用几种不同的类型,则需要以某种方式跟踪它们的类型。这就是 printf 对格式字符串所做的事情。

可变参数函数的参数列表根据称为“默认参数提升”的奇怪规则进行提升(C17 6.5.2.2/6):

如果表示被调用函数的表达式具有不包含原型的类型,则对每个参数执行整数提升,并将 float 类型的参数提升为 double。这些称为默认参数提升。如果参数的数量不等于参数的数量,则行为未定义。如果函数定义的类型包含原型,并且原型以省略号 (, ...) 结尾,或者提升后的参数类型与函数的类型不兼容参数,行为未定义。

这意味着小整数类型会提升为 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 what printf 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):

If the expression that denotes the called function has a type that does not include a prototype, the integer promotions are performed on each argument, and arguments that have type float are promoted to double. These are called the default argument promotions. If the number of arguments does not equal the number of parameters, the behavior is undefined. If the function is defined with a type that includes a prototype, and either the prototype ends with an ellipsis (, ...) or the types of the arguments after promotion are not compatible with the types of the parameters, the behavior is undefined.

Meaning that small integer types get promoted to int, but constants like 5 that are already int 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 treats int arguments as double.

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文