分类: 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 }