分类: C/C++
2015-06-23 17:12:39
首先有一点值得注意,即如下两个函数原型之间的区别:
int foo(); int bar(void);
前者的效果是忽略参数检查,下面几种函数定义和这个函数原型均没有冲突:
int foo(int a)
{
......
}
int foo(char a)
{
......
}
int foo(int a, char b)
{
......
}
而后者的意思则是说,bar这个函数没有任何参数,因此,bar只能有下面两种定义,其他定义都是非法的:
int bar()
{
......
}
int bar(void)
{
......
}
考虑下面这段代码:
1 /* Prototype function declaration. */
2 int isroot (uid_t);
3
4 /* Old-style function definition. */
5 int
6 isroot (x)
7 uid_t x;
8 {
9 return x == 0;
10 }
如果在系统中uid_t实际上是short类型,那么ISO C会对isroot中的变量x作类型提升,这样函数isroot的定义实际上变成了这样:
int
isroot (x)
int x;
{
return x == 0;
}
而程序第2行的函数原型则等价于:
int isroot (short);
这样就造成函数原型和函数定义不匹配,直接后果就是编译失败,降低了程序的可移植性。
为了解决这种问题,GCC对ISO C作了一些扩展,它允许函数原型中定义的类型可以覆盖函数定义中使用的类型。因此,即使系统中的uid_t实际上为short, 上面的那段程序也可以使用gcc正常编译通过。最终gcc把isroot的参数认作short类型——函数原型中的short覆盖了ISO C对isroot定义中的short 进行类型提升而得到的int。
这样就完全解决了这个兼容性问题吗?显然不是的,如果我使用的不是gcc,而是某种严格遵守ISO C标准的编译器,这个问题又会出现。不过现在我们可以 定义一个简单的宏来绕开这个问题,正如下面的程序所示:
1 /* Use prototypes unless the compiler is old-fashioned. */
2 #ifdef __STDC__
3 #define P(x) x
4 #else
5 #define P(x) ()
6 #endif
7
8 /* Prototype function declaration. */
9 int isroot P((uid_t));
10
11 /* Old-style function definition. */
12 int
13 isroot (x)
14 uid_t x;
15 {
16 return x == 0;
17 }