Chinaunix首页 | 论坛 | 博客
  • 博客访问: 130420
  • 博文数量: 51
  • 博客积分: 2500
  • 博客等级: 少校
  • 技术积分: 540
  • 用 户 组: 普通用户
  • 注册时间: 2007-07-21 12:33
文章分类

全部博文(51)

文章存档

2011年(1)

2010年(5)

2009年(1)

2008年(12)

2007年(32)

我的朋友

分类: C/C++

2007-08-04 19:54:49

C中的函数原型


函数原型存在的主要作用是给函数调用的参数作类型和数目检查。

首先有一点值得注意,即如下两个函数原型之间的区别:

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)
{
    ......
}

ISO C会对老式函数定义中小于一个字的参数进行类型提升。

考虑下面这段代码:

 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 }

阅读(1649) | 评论(0) | 转发(1) |
0

上一篇:Extern C的作用

下一篇:硬盘安装Fedora

给主人留下些什么吧!~~