2011-07-31 13 views
0

これは初心者のC++ポインタの質問です。なぜこのようなことが起こるのかわからない...C++:int * jの何が問題なのですか? * j = 50; ?

私はこのコードを書くと、私はそれを発見した。それは完全に有効です。

CODE1

int *j; //create an pointer j 
*j = 50; //assign 50 to the *j, meaning value pointed by address 50 is xxx 

しかし、私はそれがよりシンプルにしようとしたいとき。コンパイラが私にこのエラーメッセージを出します。

CODE2

int *j = 50; //i guess this should be the same with Code1... 

コンパイルエラー

error: invalid conversion from ‘int*’ to ‘int’ 

は、なぜそのようなことでしょうか?

+6

コード1は完全に有効ではありません。完全に定義されていない動作です。 'j'は初期化されていないポインタです。 –

+0

まあ、私は何を意味するのはちょうどコンパイル時です –

答えて

13

Cの構文には多少の曖昧さがあります。

int *j = 50; 

あなたはまだそれに値を割り当てる前に、jのための任意のメモリを割り当てられていないので、実際には、あなたが最初のコードスニペットでやっていることは危険である

int *j; 
j = 50; 

に相当します。あなたはそのようにそれのためのメモリを作成する必要があります:Cで

C++

int *j = new int; 
*j = 50; 

かのメモリの他のいくつかのブロックにポインタを指すで

int *j = (int*) malloc(sizeof(int)); 
*j = 50; 

すでに有効な:

int k; 
int *j = &k; 
*j = 50; 
printf("%d", k); // 50 

編集:あいまいさが「*」記号と関係していることを指摘する価値はあります。宣言では、int *j; * jは "jという名前のポインタ"を意味します。しかし、2行目「* j = 50」で使用している場合、*は「アドレスjの値」を意味する逆参照記号になります。

+1

これは最も説明的な答えです – Jeremy

+0

私たちがC言語でメモリを割り当てなかった場合、それはどうなるでしょうか?それはC + +で危険でしょうか? –

+3

どちらの言語でも危険です。基本的にロシアのルーレットです。ポインタ 'j'はメモリ内の不確定な位置を指し、あなたは弾丸(実際には5)をそこに発射します。正しい使用法は、誰かが傷つくことなくあなたの弾を置くことが大丈夫だと指摘しているところです。 –

2

これらは全く異なる意味を持っています。

最初にポインタを宣言し、jから50に現在あるアドレスで、intが指し示すように設定します。他の文脈がなければ、これはすでに悪いことです。 jのアドレスは初期化されておらず、メモリ内のランダムな場所に値を書き込むことで、セグメンテーション違反が発生する可能性があります。

int *j; j = 50; 

コードの2番目の部分は、それが(第2の文にアスタリスクがないことに注意してください)正確に書くようなものだ、ポインタを宣言し、あなたがそれを分ける場合は50に、それに格納されているアドレスを定義します

+0

しかし、なぜ2番目のコードがコンパイルエラーになるのですか?したがって、 '* j = 50'では、jが指すアドレスに50を代入することを意味しますか? 「j = 50」の意味は、j? –

+0

私は分かりません。試してみると、どちらの例もエラーなくコンパイルされています。 –

+0

gineはg ++ 4.4.1の下でg ++です。 –

1

両方の例が間違っています。

最初

int *j; 
*j = 50; 

格納50アドレスjします。しかし、jは決して初期化されていないので、単純に不明なアドレスに格納しています。場合によってはこれが「成功」することもありますが、これによってアプリケーションがクラッシュすることがあります。また、エラーが発生することなくアプリケーションの状態が破損することもあります。あなたが実際にやりたいことは決して決してありません。型の値と

int *j = 50; 

タイプの変数を初期化しようとする「ポインタ・ツー・INT」エラーである「INT」は、:

秒。初期のassigmentは、変数を割り当てているため、実際に等しい

int *j; 
j = 50; 

int i; 
int *j; 
j = &i; // note: no * before j. j now contains a valid address. 
*j = 50; // store 50 to the address j. After this, i == 50. 
0
int *j = 50 

されています:

int i = 50; 
int *j = &i; // j is now a pointer to i. 

か:

代わりに、あなたのような何かをしたいですそれは何でも

どちらの場合でも、ポインタが無効であるため、非常に悪い考えです。

2

int *j;を宣言した後に、int *という種類のスペースが、いくつかのアドレスがaddr_stkであり、私たちが知らないスタック(この場合)に割り当てられます。ごみ。

+--------+   +--------+ 
| ??? |----+  | xxx |  trying to store 50 here 
+--------+ |  +--------+ 
| j | |  |  | 
+--------+ |  +--------+ 
|addr_stk| +---->| ??? |  have no permission to access this location 
+--------+   +--------+ 

もしポインタ変数(オブジェクト)j*j = 50;内容を使用そこに値50を格納するアドレスとして使用されます。したがって、値50をガベージ・アドレス値を持ついくつかのアドレス位置に格納しようとします。つまり、どこにでも置くことができます。あなたが割り当てられていないメモリの場所にアクセスしようとすると、その場所を保存またはアクセスできなくなるたびに、オペレーティングシステムはそれを止めて何らかのエラーを投げます。

まず、ポインタ変数jを有効なアドレスで初期化します。これは、最初にいくつかのメモリをmallocに割り当ててから使用することによって行うことができます。他の変数(ローカルまたはグローバル)のアドレスでjを初期化する。 *jにアクセスするとき、我々はそのためのアドレス(ポインタアクセス)としてjの内容を使用して、j内部の有効なアドレスを持っている場合の両方で

int *j, i; 
j = &i; 
*j = 50; 

または

int *j; 
j = malloc (sizeof (int)); 
*j = 50; 

のような、有効で、*j解決時に有効なメモリアクセスに変換します。

重要なことは、mallocでメモリを割り当てるときは、常にメモリを解放することです。これは良い習慣であり、そうでなければ大きなプログラムではメモリリークにつながります。

1

*は、変数タイプの一部であり、その名前はではありません。

int* jは、 "私はjという名前の変数を持っています。これはintへのポインタです"という意味です。

int* j = 50(コード2)は、「jという名前の変数を持ち、これはintへのポインタであり、値は50で初期化されます」という意味です。これは許可されていません。ポインタは、明示的キャストなしで0以外の整数値で初期化することはできません。 これを回避するために明示的にキャスティングすることは、あなたが何をしているのかわからない場合、非常に悪い考えです。これらの質問をしているのなら、あなたが何をしているか分かりません試しに

エラーメッセージからこれを把握できるはずです。無効な変換は、コードがあるタイプから別のタイプへ(割り当てによって)変換しようとしますが、それは無効です。あなたが割り当てているものは、あなたが割り当てているものと互換性のあるタイプではありません。それは関係するタイプが何であるかをあなたに伝えます。

*j = 50は(コード1の2行目)「位置に値を書き込む50jポイントこと」を意味します。 jはまだ初期化されていないため、これは悪いです。 これは「未定義の振る舞い」と呼ばれ、正確には何らかの方法で失敗する可能性がありますが、動作していないとしても常に間違っています。しかし、それはコンパイルされ、ほとんどのコンパイラは本当に高い警告レベルを尋ねない限り、この種のことについて警告するつもりはありません。

関連する問題