コンパイラと構成にわたるリファレンス実装
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 }
このアセンブリ コードでは、両方の関数が同じ命令を使用して入力のロードと逆参照を行います。変数 foo。これは、コンパイラーが参照とポインターの両方を内部で同様に扱うことを示しています。
結論
参照とポインターは、C では密接に関連する概念です。標準では特定の実装を規定していませんが、コンパイラは一般に参照をポインタとして実装します。これにより、変数の範囲を超えてメモリにアクセスするための参照とポインタを効率的かつ交換可能に使用できるようになります。
以上が参照は実際に C でどのように実装されるのでしょうか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。