C旧式与新式函数的声明与定义

您所在的位置:网站首页 做旧风格叫什么名字呢 C旧式与新式函数的声明与定义

C旧式与新式函数的声明与定义

2024-07-11 22:17| 来源: 网络整理| 查看: 265

关于C语言函数的原型声明与函数定义,这里涉及了许多的内容,以此文章,记录自己所了解的知识,以备日后查阅,同时也帮助自己和大家了解这当中暗含的“陷阱”。

由于历史的原因,C语言的函数声明有旧式和新式之分,旧式就是K&R,而新式则是ANSI,如下图: 这里写图片描述

现在倡导的是使用后者,而不要使用前者,对于K&R,由于存在大量旧式代码,为了保持兼容,所以没有被正式废弃。 这两者在参数传递的时会有所区别,在K&R中,由于函数的参数也是表达式,所以会发生类型提升,即传递一个短于int的整数,函数实际所接收到的是int,如果传递的是float,函数实际接收到的是double,在被调用函数的函数体内,这些值会根据函数定义时参数的声明类型自动裁减为该类型。 你可能会感到困惑,为什么不嫌麻烦将它们提升为更大的类型,然后又直接把它们裁减为原来的大小?之所以这样做,原意是为了简化编译器—所有的东西都是同一长度。如果只固定使用几种类型,将大大简化参数的传递。所有的参数都统一为标准长度,被调用函数会根据需要对它们进行裁剪。 相反在ANSI中,如果使用了适当的函数原型,类型提升便不会发生,如果参数声明为char,则实际传递的也是char。使用新风格的函数定义,编译器就会假定参数是准确声明的,于是便不进行类型提升,并据此产生代码。

关于声明和定义,我们需要考虑4种情况

K&R C函数声明和K&R C函数定义 能够顺利调用,所传递的参数会进行类型提升ANSI C函数声明(原型)和ANSI C函数定义 能够顺利调用,所传递的参数位实际参数ANSI C函数声明(原型)和K&R C函数定义 如果使用一个较窄的类型就会失败,函数调用时所传递的是实际类型,而函数期望接收的是提升后的类型K&R C函数声明和ANSI C函数定义 如果使用一个较窄的类型就会失败,函数调用时所传递的是提升后的类型,而函数期望接收的是实际类型

所以,如果为一个K&R C函数定义增加函数原型,而原型的参数列表中有一个short参数,在参数传递时,这个原型将导致实际传递给函数的就是short类型的参数,而根据函数的定义,它期望接收的是一个int类型的参数。这样,函数从堆栈中抓取4个字节(int)而不是2个字节(short)。

下面展示两种失败情况

/* 文件1 */ /* 旧风格的定义,但它具有原型 */ int olddef (float d, char i); int main(void) { float d = 10.0; char j = 3; olddef (d, j); /* 新风格的定义,但它没有原型 */ newdef (d, j); } ---------------------------------------------------------------- /* 文件2 */ /* 旧风格的定义,但它具有原型 */ olddef(d , i) float d; char i; { printf ("olddef: float = %f, char = %x \n", d, i); } /* 新风格的定义,但它没有原型 */ newdef(float d, char i) { printf ("newdef: float = %f, char = %x \n", d, i); }

打印结果如下 这里写图片描述

所以,坚决不要在函数的声明和定义中混用新旧两种风格。

还有一种错误的用法:

int main(void) { union { double d; float f; }u; u.d = 10.0; printf ("put in a double, pull out a float f = %f \n", u.f); u.f = 10.0; printf ("put in a float, pull out a double d = %f \n", u.d); }

打印的结果为: 这里写图片描述



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3