1.1 C语言
1 #include<stdio.h>
2
3 int main(intargc, char *argv[])
4 {
5 func1();
6 func2();
7 return 0;
8 }
9
10 void func1() //warning: conflicting types for ‘func1’
11 {}
12
13 voidfunc2() //warning: conflicting typesfor ‘func2’
14 {}
该段代码用gcc编译,没有error,只有两个warning。注意warning的位置不是在5、6行,而是在10、13行!warning的告警类型是conflictingtypes,而不是函数未找到,这是为什么呢?
实际上,在函数调用前,如果没有对函数进行声明,则编译器会把第一次遇到的该函数形式(函数定义或函数调用)作为函数的声明,并将函数类型默认为int 型。编译器编译上述代码,执行到第5行处,便会将函数func1的函数原型当做intfunc1(); 编译到第10行处,发现voidfunc1() 便会告警类型冲突(返回类型int和void冲突)。如果将第10行,第13行处的函数返回类型改为int,则编译器不会出现告警。
1.2 C++
1 #include<iostream>
2
3 int main(intargc, char *argv[])
4 {
5 func1(); //error: ‘func1’ was not declared in thisscope
6 func2(); //error: ‘func2’ was not declared in this scope
7 return 0;
8 }
9
10 void func1()
11 {}
12
13 voidfunc2()
14 {}
该段代码用g++编译后,第5、6行会error。说明C++中必须要用函数原型! 也许有人会说将10-14行代码放在main函数前,就不会产生error。其实,如果被调用函数的定义出现在主调函数之前,可以不必加以声明。因为编译器已经预先知道了已定义的函数类型,会根据函数首部提供的信息对函数的调用作正确性检查。
2、函数声明的参数列表
参数列表,C语言 C++语言要求一致。这里不分开讨论。
1 #include <stdio.h>
2
3 void func1(int);
4 void func2(int c);
5
6 int main(int argc, char *argv[])
7 {
8 func1(0);
9 func2(0);
10 return 0;
11 }
12
13 voidfunc1(int a)
14 {}
15
16 voidfunc2(int b)
17 {}
(a)函数原型不要求提供变量名,有类型列表就足够了。比如第3行voidfunc1(int);
(b)原型中变量名相当于占位符,不必与函数定义中的变量名相同。比如第4行voidfunc2(int c);
3、VOID 与 没有参数
3.1 在C++中,括号为空与在括号中使用void是等效的——意味着函数没有参数。
#include <iostream>
void func1(void);
void func2();
int main(int argc, char *argv[])
{
func1();
func2();
return 0;
}
void func1()
{}
void func2(int a)
{}
使用g++编译会产生error:undefined reference to `func2()'。
3.2 在C语言中,括号为空则意味着不指出参数——这也意味着参数列表可以在后面的函数定义中列出。
#include<stdio.h>
voidfunc1();
voidfunc2();
intmain(int argc, char *argv[])
{
func1(123); //注意:这里竟然没有告警!
func2(0);
return 0;
}
voidfunc1(void)
{}
voidfunc2(int b)
{}
使用gcc编译,没有告警(即便加上-Wall选项)。
上述代码所使用的编译器均为gcc/g++ (GCC)4.4.4。
参考文献:
1、《C++ Primer Plus中文版(第6版)》
2、函数定义与声明 http://blog.csdn.net/haiyan0106/article/details/3043998