为什么一个没有参数的函数可以工作,而一个以void为参数的函数却不行?

问题描述 投票:0回答:3

在下面的代码中,我正在计算 PI 外带功能 main(). 两者之间唯一的区别是。

  • 第一段代码: 我没有传递任何参数。void calculate_pi ();
  • 第二段代码. 我明确表示没有参数可传。calculate_pi (void);.

我本以为第二种更好,但似乎不是这样。为什么会这样?

第一条代码: 。

#include <stdio.h>
#include <stdlib.h>

void calculate_pi ();

int main(void)
{

    calculate_pi ();

    return 0;
}

void calculate_pi ()
{
    int i, signo;
    double pi_approx = 1, pi_final;

    for (i = 1; i < 1000000; ++i)
        {
            signo = (i%2) ? -1 : 1;
            pi_approx = pi_approx + (float) signo / (2*i+1);
        }

    pi_final = pi_approx * 4;
    printf("%.10f\n", pi_final);
}

第二段代码

#include <stdio.h>
#include <stdlib.h>

void calculate_pi (void);

int main(void)
{

    calculate_pi (void);

    return 0;
}

void calculate_pi (void)
{
    int i, signo;
    double pi_approx = 1, pi_final;

    for (i = 1; i < 1000000; ++i)
        {
            signo = (i%2) ? -1 : 1;
            pi_approx = pi_approx + (float) signo / (2*i+1);
        }

    pi_final = pi_approx * 4;
    printf("%.10f\n", pi_final);
}
c function arguments parameter-passing void
3个回答
0
投票

声明一个空参数列表的函数,例如 void calculate_pi();,是一种旧的C语法,没有指定参数类型。在新代码中应该避免使用这种语法。最好是用参数列表来声明函数,如 int foo(char *x);. 新的语法提供了更好的类型信息,允许编译检查参数类型,并提供有用的警告和错误信息。

因为C语言使用了 () 来声明函数,而不需要指定参数类型,因此需要用不同的语法来指定一个函数有 没有 参数。使用 (void) 根据 C 2018 6.7.6.3 10.采用了特殊情况来说明这一点。

类型为未命名的参数的特殊情况。void 作为列表中的唯一一项,说明该函数没有参数。

因此,声明 void calculate_pi(void); 并没有说 calculate_pi 接受 void 参数;它说 calculate_pi 没有任何参数。这是声明一个没有参数的函数的首选方式。

由于函数不接受参数,所以应该在调用时不使用参数,使用的是 calculate_pi().

calculate_pi(void) 不是一个有效的C表达式。函数参数必须是一个值,但 void 是一个类型,而这个类型 void 不能作为函数参数出现。所以在现代C语言中,首选的代码是声明函数不接受参数。

void calculate_pi(void);

然后用无参数的方式调用它。

calculate_pi();

0
投票

这与使用 void 在函数的声明定义中作为参数类型,在函数的实际调用中作为参数。

void 在这种情况下只能作为参数使用,而不能作为函数调用的参数。类型为 void 无论如何都不能使用,因为事实上它根本没有任何价值。否则,程序将调用 未定义行为.

"无效表达式(类型为void的表达式)的(不存在的)值无论如何不得使用,隐式或显式转换(除到void外)不得应用于这种表达式。如果任何其他类型的表达式被评价为void表达式,其值或代号将被丢弃。(虚空表达式被评价为其副作用。)"

资料来源:《C18》,6.3.2。C18, 6.3.2.21

你需要调用 calculate_pi 作为 calculate_pi() 而不像 calculate_pi(void):

int main (void)
{
    calculate_pi();

    return 0;
}

"我本以为第二种更好,但似乎并非如此。"

的确,使用 void 而不是使用一个空参数列表,因为一个空参数列表的声明严格来说不是一个原型。

C标准规定(强调是我的)。

"对于标识符指定的每一个不同的实体,标识符只能在程序文本的一个叫做itsscope的区域内可见(即可以使用)。同一标识符指定的不同实体,要么有不同的作用域,要么处于不同的名称空间。有四种作用域:函数、文件、块和函数原型。(函数原型是一个函数的声明,它声明了其参数的类型.)"

因此,如果你指定了一个空的参数列表,比如f.e.Clang那样,有些编译器会给出警告。

"警告:这个函数声明不是原型[-Wstrict-prototypes]。"

但在这种情况下,问题出在其他地方,如上文所解释。


侧面说明。

  • 编译器通常会抛出一个错误,如果你提供了 void 作为默认参数,所以你的代码应该没有被编译过,请考虑换成最新的、符合标准的编译器,比如GCC或Clang。请考虑换一个最新的符合标准的编译器,比如GCC或Clang。

0
投票

最好选择第一段代码,因为你已经将 calculae_pi() 函数的返回类型指定为 void。没有必要像你在第二段代码中那样放一个void。


-1
投票

根据 @KamilCuk 的评论,正确的代码应该是这样。

#include <stdio.h>
#include <stdlib.h>
#define PI 3.14159265359

void calculate_pi (void);

int main(void)
{

    calculate_pi ();

    return 0;
}

void calculate_pi (void)
{
    int i, signo;
    double pi_approx = 1, pi_final;

    for (i = 1; i < 1000000; ++i)
        {
            signo = (i%2) ? -1 : 1;
            pi_approx = pi_approx + (float) signo / (2*i+1);
        }

    pi_final = pi_approx * 4;
    printf("%.10f\n", pi_final);
}
© www.soinside.com 2019 - 2024. All rights reserved.