Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1136638
  • 博文数量: 300
  • 博客积分: 37
  • 博客等级: 民兵
  • 技术积分: 772
  • 用 户 组: 普通用户
  • 注册时间: 2012-02-26 04:46
文章分类
文章存档

2017年(4)

2016年(7)

2015年(19)

2014年(72)

2013年(71)

2012年(127)

分类: C/C++

2015-06-23 17:12:39

原文地址:C中的函数原型 作者:gavinx

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 }

阅读(1429) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~