[在以下代码中,我正在使用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);
}
[[0]中声明一个带有空参数列表的函数是一种旧的C语法,它没有指定参数类型。在新代码中应避免使用它。优选地,用参数列表,例如void calculate_pi();
来声明函数。新语法提供了更好的类型信息,并允许编译器检查参数类型并提供有用的警告和错误消息。
因为C使用int foo(char *x);
来声明没有指定参数类型的函数,所以需要使用不同的语法来指定函数具有no参数。根据[C 2018 6.7.6.3 10:
()
作为特殊情况来表示这一点
(void)
类型的未命名参数的特殊情况是列表中的唯一项,它指定该函数没有参数。
因此,声明void
并不表示void calculate_pi(void);
接受calculate_pi
参数;它表示void
没有任何参数。这是声明不带参数的函数的首选方法。
由于该函数不接受任何参数,因此应使用calculate_pi
对其进行不带任何参数的调用。
calculate_pi()
不是有效的C表达式。函数参数必须是一个值,但是calculate_pi(void)
是类型,并且类型void
不能作为函数参数出现。因此,现代C语言中的首选代码是声明该函数不包含任何参数:
void
并且不带任何参数调用它:
void calculate_pi(void);
[在函数的声明/定义中使用calculate_pi();
作为参数类型与在实际调用函数时作为参数是有区别的。
void
只能用作参数,而不能用作函数调用中的参数。无论如何都不能使用类型为void
的表达式,因为它实际上根本不产生任何值。否则程序将调用void
。
“绝对不能使用void表达式(具有void类型的表达式)的(不存在)值,并且不得将隐式或显式转换(除void之外)应用于此类表达式。任何其他类型都将作为void表达式求值,其值或指示符将被丢弃。(对void表达式的副作用进行求值。)“
来源:C18,6.3.2.2 / 1
您需要将undefined behavior称为calculate_pi
,而不是calculate_pi()
:
calculate_pi(void)
“ 我本以为第二个更好,但事实并非如此。”
确实最好在声明/定义处使用int main (void)
{
calculate_pi();
return 0;
}
而不是使用空参数列表,因为严格认为带有空参数列表的声明不是原型。
C标准规定(强调我的::)>
“对于标识符指定的每个不同实体,该标识符仅在称为其范围的程序文本区域内可见(即,可以使用。)由同一标识符指定的不同实体要么具有不同的范围,要么具有不同的名称空间,共有四种作用域:函数,文件,块和函数原型(一个函数原型是一个声明其参数类型的函数的声明
。)“因此,如果您指定一个空的参数列表,例如f.e,则某些编译器会发出警告。 lang做:
“ 警告:此函数声明不是原型[-Wstrict-prototypes]
”但是在这种情况下,问题出在其他地方,如上所述。
旁注:
void
作为参数,则编译器通常会引发错误,因此甚至不应该编译您的代码。请考虑换用最新的,符合标准的编译器,例如GCC或Clang。基于@KamilCuk的注释,那么正确的代码应为: