pg474,K.N.King
“C99中的一般规则是,如果a的所有顶级声明 特定文件中的函数包括内联但不是extern,然后是 该文件中函数的定义是内联的。“
“如果在程序中的任何地方使用该功能(包括文件) 它包含其内联声明),然后是外部声明 该函数需要由其他文件提供。当。。。的时候 函数被调用,编译器可以选择执行普通调用 (使用函数的外部定义)或执行内联扩展 (使用函数的内联定义)。没有办法分辨哪个 编译器将做出的选择,因此这两个定义至关重要 保持一致。“
“具有静态存储持续时间的变量是一个特殊问题 具有外部链接的内联函数“
但我认为你无法通过外部链接调用函数!该 编译器会出错:
第473页
“所以试图从中调用平均值 另一个文件将被视为错误“
“因此,C99对内联施加以下限制 具有外部链接的功能(但不具有内部链接的功能): 该函数可能未定义可修改的静态变量。 该函数可能不包含对具有内部变量的引用 联动“。
为什么?如果函数是内联和外部,那么即使它确实声明了一个 static int i;由于功能无法链接到你无法调用它, 但是不会在内联函数之外创建静态变量 堆栈框架 - 所以你应该能够链接到它?做内联函数 有一个堆栈框架?这是怎么回事?
答案 0 :(得分:12)
我知道我写了很多,但我试图解释存储和链接的概念和我的文本解释。希望这有帮助!
" C99中的一般规则是,如果a的所有顶级声明 特定文件中的函数包括内联但不是extern,然后是 该文件中函数的定义是内联的。"
什么是:"函数的顶级声明" ??
函数的声明以与变量声明类似的形式使用。它是一个声明函数名称,返回类型和参数类型的语句。函数定义是函数的实际代码。
示例声明:
int foo( int bar );
示例定义:
int foo( int bar ){
return -bar;
}
顶级函数声明只是文件范围内的声明(即,在任何块之外)。这通常是所有函数声明的地方,尽管可以在其他函数内声明和定义函数。
"如果在程序中的任何地方使用该功能(包括文件) 它包含其内联声明),然后是外部声明 该函数需要由其他文件提供。当。。。的时候 函数被调用,编译器可以选择执行普通的 调用(使用函数的外部定义)或执行内联 扩展(使用函数的内联定义)。没有办法 告诉编译器将选择哪个选项,这对两者来说至关重要 定义是一致的。"
咦???他在这说什么?
首先,什么是联动?变量或函数的链接定义了编译器如何处理该对象的多个实例。没有联系的标识符总是“个人”。也就是说,程序内标识符的多个声明总是被视为单独/不同的实体。函数参数和局部变量没有联系。对外部链接的标识符的所有引用都指向同一实体。这是C关键字' extern'。默认情况下,全局标识符具有外部链接。这意味着,例如,如果你有全局变量" int x;"在程序的两个源文件中,它们将链接在一起并视为同一个变量。内部链接意味着一个源文件中的标识符的所有声明都引用单个实体,但是其他源文件中的相同标识符的声明引用不同的实体。这是制作东西的私人方式"到一个文件。这是文件范围中的C关键字' static'
现在,回到段落。函数不能定义多次。因此,想要使用其他源文件中的函数的源文件需要包含外部声明(这是进行函数调用所需的信息)。本段解释的是当文件具有内联函数的外部声明时会发生什么。编译器必须选择是否应该获取内联定义并将其插入调用函数的位置,或者是否应该保留外部链接,使执行跳转到代码文本,就像正常一样;并且没有办法预测编译器将做出什么选择。
"具有静态存储持续时间的变量是一个特殊问题 具有外部链接的内联函数"
但我认为你无法通过外部链接调用函数!该 编译器会给出一个错误:pg 473"所以试图调用平均值 来自另一个文件将被视为错误"
如果您无法调用在不同源文件中定义的函数(即外部链接函数),那么C确实是一种非常弱且无聊的语言!
"因此,C99对内联施加以下限制 具有外部链接的功能(但不具有内部链接的功能): 该函数可能未定义可修改的静态变量。功能 可能不包含对具有内部链接的变量的引用。"
为什么?如果函数是内联函数和外部函数,那么即使它确实声明了 一个静态的int i;由于该功能无法链接到您无法呼叫 它,但不会在内联之外创建静态变量 函数stack-frame - 所以你应该能够链接到它?内联 功能有堆栈框架?这里发生了什么?
静态存储的变量是不属于执行堆栈的变量。它的空间在程序开始运行之前分配一次,并在整个执行过程中存在。它们保留其初始值,直到分配不同的值。默认情况下,全局变量(文件范围)是静态存储的。这与自动存储的变量形成对比,后者在程序执行进入声明它们的块之前在堆栈上分配,并在执行离开该块时被丢弃。默认情况下,局部变量(块范围)是自动的。
回到问题:内联函数中静态存储变量的问题是什么?函数内的静态存储变量的假设是该函数只有一个定义,因此只有该静态变量的一个定义。但是,根据定义,内联是函数定义的重复,因此您不需要在函数调用期间跳转代码文本。如果函数中存在静态变量,那么你将不得不跳转到它的存储位置,从而破坏了内联的目的,即拥有所有内容的副本"就在那里"。解决方案:要求变量不可修改,以便编译器可以内联永久值。
关于你的最后一个问题:内联函数确实有一个堆栈框架:它与调用函数的堆栈框架相同,因为内联函数的代码文本正在按顺序复制避免正常外部函数跳跃的标准指令开销。