私はCプログラミングが初めてです。クラスの課題の 1 つを解決しているときに、次のコード スニペットを見つけました。私はそれが何をするのか理解していませんでした。
次の C 構文の意味を教えてください。
((char *)0 +1) or ((int*)0 +1))
パーツは、アドレス 0 に文字データへのポインターを作成します。(char *) 0
アドレス 0 へのポインター ( NULL
C でのポインターとも呼ばれます) はポインター演算では使用できないため、このアドレスは 1 ずつインクリメントされ、未定義の動作がトリガーされます。2 番目の部分は、整数データへのポインターを除いて同じことを行います。
コンパイラが単純NULL
にアドレスとして処理する場合 (これは一般的ですが、これが未定義の動作である理由である必要はありません)、結果のアドレスは、数値的に見ると同じではありません。C でのポインター演算は、指されているタイプで、通常はsizeof (int) > sizeof (char)
.
次の C 構文の意味を教えてください。
((char *)0 +1) or ((int*)0 +1))
C標準の条件は定義されていないため、何もありません。このコードは、C コンパイラの一部で未定義の動作を引き起こします。説明させてください:
C では、すべてのポインターは、ポインターが逆参照する型のオブジェクトを指すか、または 0 である可能性があり、これはnull ポインターと呼ばれます。→pointer 演算では null ポインタを使用できません。
金属上のヌル ポインターの実際の表現、つまり変数がマシン上に持つビットは、すべてゼロとは異なる場合があることに注意してください。しかし、C 側では、ヌル ポインターは常に値 0 の整数と等しいと比較されます。さらに、異なる型のヌル ポインターも定義により等しいと比較されます。ただし、異なる型の null 以外のポインタを比較すると、未定義の動作が発生します。また、任意のポインターをポインターにキャストしてvoid*
戻すこともできます。また、すべてのポインターを整数型にキャストしてuintptr_t
戻すこともできます。しかし、型 A へのポインターから型 B のポインター (ここで B は ではないvoid*
) へのキャストは、未定義の動作を引き起こします。
ただし、特別な関数malloc
は、C 言語仕様によって定義されており、void*
任意のポインター型にキャストできるポインターを返します。しかし、それを使用しての配列にメモリを割り当てchar
、後でそれをこれにキャストすると、int
未定義の動作が再び呼び出されるとします。
ここで、「未定義の動作とは何ですか?」と尋ねるかもしれません。まあ、それは単に、言語標準がそれを定義しておらず、実装者が適切と思われる方法でそれを実行できることを意味します. ほとんどのプラットフォームでは、次のようなものを書くと((char*)0 + 1)
単純に予想されること (アドレス 1 を指すポインターを作成する) が行われる可能性がありますが、コンパイラーに人工知能を構築させることもできます。世界中で、人間をバッテリーに変えます。だからあなたがすることに注意してください;)
Cでは、使用するタイプをコンパイラに伝える必要があります。これは「キャスト」と呼ばれます。例えば:
char *c; //define c as "char pointer" (pointer to char)
c = ((char *)0 + 1); //this casts "0 + 1" to "char pointer" type, in this example not strictly necessary but adds some clarification to code