などと書いていたのですが
char *x=NULL;
という前提で
char *x=2;
はアドレス 2 に char
ポインタを作成します。
しかし、The GNU C Programming Tutorial には、 int *my_int_ptr = 2;
は整数値 2
を my_int_ptr
が割り当てられたときの任意のランダムアドレスに格納すると書かれています。
これは、私の char *x=NULL
が char
にキャストされた NULL
の値をメモリ上のランダムなアドレスに代入していることを意味しているように思えます。
一方
#include <stdlib.h>
#include <stdio.h>
int main()
{
char *x=NULL;
if (x==NULL)
printf("is NULL\n");
return EXIT_SUCCESS;
}
は、実際には、印刷します。
はNULL
を出力してしまうので、未定義の動作に依存しているのではないか、少なくとも仕様に満たない動作なのではないかと心配になり
char *x;
x=NULL;
と書くべきかと思います。
_CのポインタをNULLに初期化することは可能ですか?
TL;DR はい、とても。
_一方、
int *my_int_ptr = 2;
という単一の初期割り当てだけを使用すると、プログラムはmy_int_ptr
が指すメモリ位置の内容を値 2 で埋めようとします。my_intptr` はゴミで埋まっているので、どんなアドレスでもかまいません。[...]
まあ、彼らはare間違っている、あなたは正しい。
この文に対して、(とりあえず、ポインタから整数への変換は実装で定義された動作であることを無視する)。
int * my_int_ptr = 2;
my_int_ptrは変数 (
intへのポインタ型) で、それ自身のアドレス (型: 整数へのポインタのアドレス) を持っており、あなたは
2` という値をそのアドレスに格納しています。
ここで、my_int_ptr
はポインタ型なので、 my_int_ptr
が指すメモリ位置にある "type" の値を指すと言えます。つまり、ポインタ変数の値を代入しているのであって、ポインタが指すメモリ位置の値を代入しているわけではありません。
ですから、結論から言うと
char *x=NULL;
はポインタ変数 x
を NULL
に初期化しますが、ポインタが指すメモリアドレスの value は初期化しません。
これは、以下のものと 同じ です。
char *x;
x = NULL;
さて、厳密に準拠すると、次のような文になります。
int * my_int_ptr = 2;
のような記述は制約違反を伴うため、違法です。はっきり言って
はポインタ変数で、
int *` 型です。2
は、定義により int
型である。で、これらは互換性のない型なので、この初期化は Lundin's answer で説明した §6.5.16.1/P1 章で述べた単純代入のルールに違反しているので無効となるのです。
初期化が単純代入の制約とどのように関連しているかに興味がある人のために、 C11
, chapter §6.7.9, P11 を引用しておきます。
スカラーの初期化子は1つの式でなければならず、オプションで中括弧で囲むことができる。その オブジェクトの初期値は、式の値(変換後)です。 単純な代入と同じ制約と変換が適用され,スカラーの型は非限定版となる。 の型を,その宣言された型の非限定版とみなして,単純代入と同じ型制約と変換が適用される**。
int *my_int_ptr = 2
とします。
は、my_int_ptr が割り当てられたときに、そのランダムなアドレスに整数値 2 を格納します。
これは完全に間違っています。もしこれが実際に書かれているのであれば、もっと良い本やチュートリアルを入手してください。
int *my_int_ptr = 2はアドレス 2 を指す整数ポインタを定義しています。アドレス
2` にアクセスしようとすると、ほとんどの場合クラッシュします。
my_int_ptr = 2は、つまり
intを含まない行で、
my_int_ptrが指す任意のランダムなアドレスに値 2 を格納します。このように、ポインタが定義されているときに
NULLを代入することができます。char *x=NULL;
は完全に有効な C 言語です。
Edit: これを書いている間、私は整数からポインタへの変換が実装で定義された動作であることを知りませんでした。詳しくは @M.M と @SouravGhosh の回答を参照してください。