【问题标题】:function parameter receives a int "b" number but print a random number (function calling function)函数参数接收一个 int "b" 数字但打印一个随机数(函数调用函数)
【发布时间】:2018-05-19 12:32:44
【问题描述】:

我确实在下面的代码中注释了问题出在哪里,当调用 pow 函数时,exp 参数变得疯狂。代码的目标是接收用户输入并求解表达式 x/(1+t)^n。

#define _CRT_SECURE_NO_WARNINGS

#include <stdio.h>

float val();
float pow();

float val(float x, int n, float t) {

    float res = 0;

    for (int i = 0; i < n; i++) {
        printf("exp = %d\n", i+1); // real value exp start equals 1
        res += x / pow(1 + t, i+1);
    }
    return res;
}

float pow(float base, int exp) {
    int i = 0;
    float res = 1;
    printf("exp = %d", exp); // here starts the problem 
    if (exp == 1) {
        return base;

    }
    while (i < exp) {
        res *= base;
        i++;
        printf("i = %d\n", i);
        printf("exp = %d\n", exp);
        getchar();
    }
    return res;
}

main() {
    int n;
    float x, t, res;

    printf("type x,n,t\n");
    scanf("%f %d %f", &x, &n, &t);
    res = val(x, n, t);
    printf("VAL = %f\n", res);


}

输出:

type x,n,t
6
2
2
exp = 1
exp = 1074266112i = 1
exp = 1074266112
i = 2
exp = 1074266112

发生了什么事伙计们? 感谢您的关注:)

【问题讨论】:

  • 有一个标准库函数pow,你应该给你的函数起个不同的名字以避免链接冲突
  • 好建议!!确实改变了浮动功率(浮动基数,int exp)希望一个不存在了:)

标签: c function parameter-passing


【解决方案1】:

不要使用旧式已弃用的非原型前向声明:

float val();    /* This syntax should never be used */
float pow();

当你声明一个函数时,声明它的完整原型:

float val(float x, int n, float t);
float pow(float base, int exp);

另外,请考虑使用double 而不是float


从最初的结果可以猜到,你的程序表现出未定义的行为;在这种情况下,您调用pow 的参数类型与其参数类型不兼容。旧式不推荐使用的声明样式

float pow();

没有指定pow 的参数类型是什么,甚至没有指定它期望的参数类型。实际上,它告诉编译器“相信我,我会提供正确类型的参数。”

但是不可能遵守这个承诺,因为pow 期望float 作为它的第一个参数,并且编译器对提供给没有原型声明的函数的所有参数执行默认参数提升。默认促销之一将float 转换为double,因此不可能提供float 参数。如果您使用 doubles 而不是 floats,您将不会遇到这个特殊问题,并且您可能会继续使用已被劝阻近 30 年的语法。

顺便说一句,这个问题在val中并没有出现,因为val的定义在你使用之前就已经出现了。当然,定义确实指定了参数类型,并且填充了无原型前向声明中省略的信息。

但底线是上面提供的简单建议:不要使用旧式函数声明。每个函数都应该用一个完整的原型声明,指定其所有参数的类型。 (如果需要声明不带参数的函数,请使用特殊参数列表(void),而不是空参数列表。)

【讨论】:

  • 我做了一些改动,输出看起来更好,但仍然很奇怪。输出:类型 x,n,t \n 6\n 2\n 2\n exp = 1 \n exp = 1exp = 2 \n exp = 2i = 1 \n exp = 2 \n i = 2 \n exp = 2 \n
  • @raijin:我看不出那个输出有什么问题。
  • 解释 为什么float val() 声明与 float val(float x, int n, float t) {...} 定义混合使用是不好的。对感兴趣的人的简短回答:使用float val() 声明,调用代码将应用默认参数提升,而float val(float x, int n, float t) 定义期望接收非提升参数。
  • @AndrewHenle:好的,我做到了,尽管解释仅适用于 OP 的 pow 函数,不适用于 val。老实说,我认为谜团不在于为什么这段代码不起作用,而在于为什么人们仍然普遍使用一种可能在他们出生之前就被弃用的语法。
【解决方案2】:

战俘:

float pow(float base, int exp) 
{

    float res = 1;
    if (exp > 0)
    {
         while(exp --)
         {
            res *= base;
         }
    }
    else
    {
        while(exp ++)
        {
            res /= base;
        }
    }

    return res;
}

main() 
{
    int i;
    for (i = -5; i <= 5; i++)
    {
        printf("5 ^^ %d = %f\n", i, pow(5.0f,i));
    }
}

并完成

#include <stdio.h>

float power(float base, int exp) 
{

    float res = 1;
    if (exp > 0)
    {
    while(exp --)
    {
            res *= base;
    }
    }
    else
    {
    while(exp ++)
    {
        res /= base;
    }
    }

    return res;
}

float eq(float x, float t, int n)
{
    return x / power(1 + t, n); 
}

int main() 
{
    float x,t;
    int i,n;

    for (i = -5; i <= 5; i++)
    {
        printf("5 ^^ %d = %f\n", i, power(5.0f,i));
    }

    scanf("%f %f %d\n", &x, &t, &n);
    printf("x = %f, t = %f, n = %d\n", x, t, n);
    printf("1/(1+t)^^n = %f", eq(x, t, n));
}

【讨论】:

  • 你应该解释你做了什么改变以及为什么
猜你喜欢
  • 1970-01-01
  • 2018-12-29
  • 2019-02-19
  • 1970-01-01
  • 1970-01-01
  • 2011-03-18
  • 2016-09-20
  • 1970-01-01
  • 2023-03-22
相关资源
最近更新 更多