跨编译器和配置的引用实现
C 中的引用是一个强大的功能,可以高效地访问超出变量范围的内存。但它们实际上是如何实现的呢?
标准建议和实现差异
C 标准没有强制要求特定的实现以供参考。但是,编译器通常遵循某些准则:
示例程序和编译器输出
为了演示引用的内部实现,请考虑以下程序:
#include <stdio.h> #include <stdlib.h> int byref(int &foo) { printf("%d\n", foo); } int byptr(int *foo) { printf("%d\n", *foo); } int main() { int aFoo = 5; byref(aFoo); byptr(&aFoo); }
在禁用 LLVM 和优化的情况下编译此程序会生成相同的汇编代码byref 和 byptr 函数:
define i32 @_Z5byrefRi(i32* %foo) { %foo_addr = alloca i32* ; <i32**> [#uses=2] %retval = alloca i32 ; <i32*> [#uses=1] %"alloca point" = bitcast i32 0 to i32 ; <i32> [#uses=0] store i32* %foo, i32** %foo_addr %0 = load i32** %foo_addr, align 8 ; <i32*> [#uses=1] %1 = load i32* %0, align 4 ; <i32> [#uses=1] %2 = call i32 (i8*, ...)* @printf(i8* noalias getelementptr inbounds ([4 x i8]* @.str, i64 0, i64 0), i32 %1) ; <i32> [#uses=0] br label %return return: ; preds = %entry %retval1 = load i32* %retval ; <i32> [#uses=1] ret i32 %retval1 } define i32 @_Z5byptrPi(i32* %foo) { %foo_addr = alloca i32* ; <i32**> [#uses=2] %retval = alloca i32 ; <i32*> [#uses=1] %"alloca point" = bitcast i32 0 to i32 ; <i32> [#uses=0] store i32* %foo, i32** %foo_addr %0 = load i32** %foo_addr, align 8 ; <i32*> [#uses=1] %1 = load i32* %0, align 4 ; <i32> [#uses=1] %2 = call i32 (i8*, ...)* @printf(i8* noalias getelementptr inbounds ([4 x i8]* @.str, i64 0, i64 0), i32 %1) ; <i32> [#uses=0] br label %return return: ; preds = %entry %retval1 = load i32* %retval ; <i32> [#uses=1] ret i32 %retval1 }
在此汇编代码中,两个函数使用相同的指令来加载和取消引用输入变量富。这表明编译器在底层以类似的方式对待引用和指针。
结论
引用和指针是 C 中密切相关的概念。虽然标准没有规定具体的实现,但编译器通常将引用实现为指针。这允许高效且可互换地使用引用和指针来访问变量范围之外的内存。
以上是C 中的引用实际上是如何实现的?的详细内容。更多信息请关注PHP中文网其他相关文章!