私は C プログラマーではありませんが、C プログラムを Delphi に翻訳しています。次のようなステートメントの意味を理解できないことを除いて、すべてが順調に進んでいます。
if (result1)
*result1 = t2;
割り当ては常に実行され、その後何らかの条件でテストされるように見えますか?
完全な C プログラムはhttp://en.wikipedia.org/wiki/Talk%3ATrilatationにリストされています。
私は C プログラマーではありませんが、C プログラムを Delphi に翻訳しています。次のようなステートメントの意味を理解できないことを除いて、すべてが順調に進んでいます。
if (result1)
*result1 = t2;
割り当ては常に実行され、その後何らかの条件でテストされるように見えますか?
完全な C プログラムはhttp://en.wikipedia.org/wiki/Talk%3ATrilatationにリストされています。
C では、整数とブール値の間に同化があります。ゼロ以外の数値は真を意味します。C 99 ではbool
(C++ の手順に従って) 型が追加されましたが、これらの非常に一般的な使用法を根絶するのは困難です (また、この規則を使用する多くのレガシー ソース コードもあります)。
その文の本当の意味は次のとおりです。
if ( result1 != NULL ) {
*result1 = t2;
}
これは、result1
がポインタであることを意味し、この行の前に予想されるメモリ割り当てが成功した場合、値を格納するために使用されますt2
。
では、これはポインタと何の関係があるのでしょうか? ポインタは基本的に整数 (メモリ アドレス) であり、NULL は (非常に一般的ですが、常にではありません) ゼロです。result1 != NULL
したがって、「result1」はまたはとして解釈できますresult1 != 0
。
最後にNULL
は、メモリ割り当て (またはその他のメモリ操作) が失敗したときに返されるため、使用する前にポインタが生きている (つまり、そうでないNULL
) ことをテストするのが一般的です。
ポインターresult1
が ではないかどうかをテストしますnull
。true
t2
の値として割り当てられる場合result1
C/C++ では、ポインターを逆参照するのは未定義の動作です。NULL
要するに、そうすると本当に悪いことが起こる可能性があります。
NULL
そのため、逆参照する前にポインターをチェックすることを常にお勧めします。
上記のコードはそれを行います。
結果はポインターへのポインターのように見えます。null でない場合は、それが指しているポインタを t2 に向けます。
result1 が null でない場合、result1 は t2 をアドレス指定するアドレス ポイントを指します
関数パラメーターを介して戻り結果を渡したい場合、これは実際にはCで一般的なパターンです。var
C関数にはパラメーターがないため、値へのポインターをパラメーターとして渡すことでアイデアをシミュレートし、関数はポインターが指す場所に代入することで値を設定できます。
その行はmain
次のようになります。
result = trilateration(&o1, &o2, p1, r1, p2, r2, p3, r3, MAXZERO);
変数 o1 と o2 のメモリ内のアドレスを指すポインターを作成します (これが&
意味することです)。次に、関数の行
*result1 = t2;
を指しているもの、この場合は に代入t2
します。result1
o1
この線
if (result1)
ポインターが「真」かどうかをテストします (偽は 0 と同じであり、ゼロ以外の値は C では真です)。
if (result1 != NULL) // NULL is effectively the same as 0.
これが行われる理由は、関数の最初の引数として NULL を渡すことが合法であるためです。2 つの結果値のうちの 1 つだけを取得することに関心がある場合は、これを行うことができます。だから、あなたは安全に行うことができます
result = trilateration(NULL, &o2, p1, r1, p2, r2, p3, r3, MAXZERO);
計算を気にしない場合o1
。
result1
ポインターです。その値は、メモリ内の別のオブジェクトの場所です。
C boolean コンテキストでは、値がゼロの整数式は として評価されますがfalse
、値がゼロでない整数式は として評価されtrue
ます。ポインター コンテキストでは、ゼロ値の整数式はNULL ポインター定数として扱われます。これは、明確に定義された「どこにもない」ことを表し、無効なポインター値と見なされます。
したがってif (result1)
、ポインターの値をテストします。0 の場合は、意味のresult1
ある場所を指していないことを意味し、0 は も意味するためfalse
、ステートメントの本体はif
実行されません。省略形の書き方if (result1 != NULL)
です。値が 0 でない場合、それは有効なポインター値であり (うまくいけば、以下を参照)、テストに合格し、式は の値をが指す場所に*result1 = t2
書き込みます。 t2
result1
ポインタに関するいくつかの注意事項: まず第一に、NULL 以外のポインタ値は、その値がライブ オブジェクトのアドレスに対応していない可能性があるという点で、必ずしも有効なポインタであるとは限りません。無効なポインターを逆参照(指すメモリーにアクセス) しようとしたときの動作は未定義です。プログラムが完全にクラッシュするか、悪い状態で実行し続けるか、問題なく動作する可能性があります。したがって、通常は、宣言時にすべてのポインターを NULL に初期化し、ポインターが指しているものが使用されなくなったときに NULL に設定することをお勧めします。
次に、ヌル ポインター定数は常にゼロ値ですが、実装で使用されるヌル ポインター値はゼロである必要はありません。これらの値をマップするのはコンパイラ次第なので、ソース コードに関する限り、NULL は常に 0 を意味します。それが基盤となるOSに当てはまるとは思わないでください。
if (result1 != NULL)
{
*result1 = t2;
}
result1 がnull
ポインターの場合、その行*result = t2
は SEGFAULT を引き起こすはずです。