And*_*ton 30 c promotions prototype function
在C语言中调用函数时,我有一些关于默认参数提升的问题.这里是6.5.2.2节"函数调用" C99标准(pdf)中的第6,7和8段(强调添加并分为列表以便于读):
第6段
- 如果表示被调用函数的表达式具有不包含原型的类型,则对每个参数执行整数提升,并将具有类型的参数
float提升为double.这些被称为默认参数促销.- 如果参数数量不等于参数数量,则行为未定义.
- 如果使用包含原型的类型定义函数,并且原型以省略号(
, ...)结尾或者促销后的参数类型与参数类型不兼容,则行为未定义.- 如果使用不包含原型的类型定义函数,并且促销后的参数类型与促销后的参数类型不兼容,则行为未定义,但以下情况除外:
- 一个提升类型是有符号整数类型,另一个提升类型是相应的无符号整数类型,并且该值可在两种类型中表示;
- 这两种类型都是指向字符类型的限定或非限定版本的指针
void.
第7段
- 如果表示被调用函数的表达式具有包含原型的类型,则将参数隐式转换为相应参数的类型,就像通过赋值一样,将每个参数的类型作为其声明的非限定版本类型.
- 函数原型声明符中的省略号表示法导致参数类型转换在最后声明的参数之后停止.默认参数提升是在尾随参数上执行的.
第8段
- 没有其他转换是隐式执行的; 特别是,参数的数量和类型不会与函数定义中不包含函数原型声明符的参数的数量和类型进行比较.
char和short对int/ unsigned int和float到doubleprintf)的可选参数受默认参数提升的约束为了记录,我对函数原型的理解是这样的:
void func(int a, char b, float c); // Function prototype
void func(int a, char b, float c) { /* ... */ } // Function definition
Run Code Online (Sandbox Code Playgroud)
我很难完成这一切.以下是我的一些问题:
APr*_*mer 33
具有原型的函数的(非可变参数)参数被转换为相应的类型,可以是char,short,float.
没有原型和可变参数的函数的参数受默认参数提升的约束.
如果使用原型定义函数并在没有原型的情况下使用它,反之亦然,并且它具有char,short或float类型的参数,那么在运行时可能会出现问题.如果提升的类型与读取参数列表时使用的类型不匹配,则可变函数会遇到相同类型的问题.
示例1:使用原型定义函数并在没有原型的情况下使用它时出现问题.
definition.c
void f(char c)
{
printf("%c", c);
}
Run Code Online (Sandbox Code Playgroud)
use.c
void f();
int main()
{
f('x');
}
Run Code Online (Sandbox Code Playgroud)
可能会失败,因为将传递一个int并且函数需要一个char.
示例2:定义没有原型的函数并将其与一个原型一起使用时出现问题.
definition.c
void f(c)
char c;
{
printf("%c", c);
}
Run Code Online (Sandbox Code Playgroud)
(这种定义很老式)
use.c
void f(char c);
int main()
{
f('x');
}
Run Code Online (Sandbox Code Playgroud)
可能会失败,因为期望int,但会传递一个char.
注意:您将注意到标准库中的所有功能都具有默认促销产生的类型.因此,在添加原型的过渡期间,它们不会引起问题.
Nor*_*sey 33
Upvoted AProgrammer的答案 - 那些是真货.
对于那些想知道为什么会这样的人:在1988年之前的黑暗时代,经典的"K&R"C中没有函数原型这样的东西,并且默认的论证促销是因为(a)基本上存在的"自由",因为它的成本没有更多的把一个字节在寄存器中,而不是把一个字在寄存器中,和(b)以减少在参数传递的潜在错误.第二个原因从未完全消除它,这就是为什么在ANSI C中引入函数原型是C语言中有史以来最重要的变化.
至于何时启动默认促销:默认参数促销在参数的预期类型未知时使用,也就是说当没有原型或参数是可变参数时.
caf*_*caf 15
您的困惑源于对术语的轻微误解 - 声明和定义都可以包括原型(或不包括原型):
void func(int a, char b, float c);
Run Code Online (Sandbox Code Playgroud)
这是一个包含原型的函数声明.
void func(int a, char b, float c) { /* ... */ }
Run Code Online (Sandbox Code Playgroud)
这是一个包含原型的函数定义.
"Prototyped"和"non-prototyped"只是函数类型的属性,声明和定义都引入了函数的类型.
所以你可以有一个没有原型的声明:
void func();
Run Code Online (Sandbox Code Playgroud)
或者你可以有一个没有原型的定义(K&R C风格):
void func(a, b, c)
int a;
char b;
float c;
{ /* ... */ }
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
13422 次 |
| 最近记录: |