<ポインタの宣言>
int *ip;
このように、ポインタは、それが記憶するアドレスのメモリ領域のデータ型と、ポインタ宣言子(*)を用いて宣言します。
<ポインタの初期化>
他の変数と同様、ポインタも宣言しただけでは、ポインタ変数のためのメモリ領域が確保されるだけで、その中身(アドレスの値)は不定です。
int *ip; /* int型のポインタ変数ipを宣言 */
*ip = 10; /* ipの中身(アドレス)は初期化されていないので... */
上の例のように、ipを初期化する前に*ipをつかって値を代入しようという操作は、あらぬアドレスに書き込もうとすることになるので、とんでもないエラーになります。
ポインタの指す先に値を代入する前に、必ず適切なアドレスの値でポインタを初期化する必要があります。
int n = 0; /* int型の変数nを宣言。nにあるアドレスのメモリが割り当てられる */
int *ip; /* int型のポインタ変数ipを宣言 */
ip = &n; /* ipにnのアドレスを代入 → ipはnを指す */
(あるいはまとめて int *ip = &n;)
double
data[10]; /*
double型の配列dataを宣言。dataにメモリが割り当てられる */
double *dp; /*
double型のポインタ変数dpを宣言 */
dp = data; /*
dpに配列dataの先頭アドレスを代入 → dpはdata[0]を指す */
(あるいはまとめて
double *dp = data)
このようにすれば、ipとdpは、それぞれ変数n、配列dataに対して確保されたメモリのアドレスで初期化されるので、*ipや*dpをつかって値を書き込んでもOKです。
もうひとつ、プログラム実行中に「動的に」確保されたメモリ領域のアドレスで初期化する、というケースもありますが、それについては「動的なメモリ領域の確保」の項目を参照してください。