なぜポインタを使うのか?[closed] 質問する

なぜポインタを使うのか?[closed] 質問する

これは本当に基本的な質問だとはわかっていますが、高級言語でいくつかのプロジェクトをコーディングした後、基本的な C++ プログラミングを始めたばかりです。

基本的に、3つの質問があります。

  1. 通常の変数ではなくポインタを使用するのはなぜですか?
  2. ポインタはいつ、どこで使用すればよいですか?
  3. 配列でポインターを使用するにはどうすればよいでしょうか?

ベストアンサー1

  • 通常の変数ではなくポインタを使用するのはなぜですか?

簡単に答えると、やめてください。 ;-) ポインターは、他に何も使用できない場合に使用します。適切な機能が不足している、データ型が欠落している、または純粋にパフォーマンスが優先される場合に使用します。詳細は以下をご覧ください。

  • ポインタはいつ、どこで使用すればよいですか?

簡単に答えると、他に何も使用できないということです。C では、文字列などの複雑なデータ型はサポートされていません。また、変数を関数に「参照渡し」する方法もありません。ポインターを使用する必要があります。また、リンク リスト、構造体のメンバーなど、事実上あらゆるものを指すようにポインターを使用することもできます。ただし、ここではそのことについては触れません。

  • 配列でポインターを使用するにはどうすればよいでしょうか?

少しの努力と多くの混乱を伴います。 ;-) int や char などの単純なデータ型について言えば、配列とポインターの間にはほとんど違いはありません。これらの宣言は非常に似ています (ただし、同じではありません。たとえば、sizeof異なる値を返します)。

char* a = "Hello";
char a[] = "Hello";

配列内の任意の要素に次のようにアクセスできます。

printf("Second char is: %c", a[1]);

配列は要素 0 から始まるので、インデックスは 1 です。:-)

あるいは、同じようにこうすることもできます

printf("Second char is: %c", *(a+1));

ポインタ演算子 (*) が必要なのは、printf に文字を印刷するように指示しているからです。* がなければ、メモリ アドレスの文字表現自体が印刷されます。ここでは、代わりに文字自体を使用しています。%c の代わりに %s を使用した場合、printf に 'a' に 1 を加えた値 (上の例) で示されるメモリ アドレスの内容を印刷するように要求し、先頭に * を置く必要はありませんでした。

printf("Second char is: %s", (a+1)); /* WRONG */

しかし、これは 2 番目の文字だけではなく、ヌル文字 (\0) が見つかるまで、次のメモリ アドレスのすべての文字を印刷します。そして、ここから状況は危険になり始めます。%s フォーマッタを使用して、char ポインタではなく、誤って整数型の変数を印刷しようとしたらどうなるでしょうか。

char* a = "Hello";
int b = 120;
printf("Second char is: %s", b);

これは、メモリ アドレス 120 で見つかったものをすべて印刷し、ヌル文字が見つかるまで印刷を続けます。この printf ステートメントを実行するのは間違っており、違法ですが、ポインターは多くの環境では実際には int 型であるため、おそらくいずれにせよ機能します。代わりに sprintf() を使用して、この長すぎる「char 配列」を、限られたスペースしか割り当てられていない別の変数に割り当てた場合に発生する可能性のある問題を想像してください。メモリ内の他の何かを上書きしてしまい、プログラムがクラッシュする可能性があります (運が良ければ)。

ああ、宣言時に char 配列 / ポインタに文字列値を割り当てない場合は、値を割り当てる前に十分な量のメモリを割り当てる必要があります。 malloc、calloc などを使用します。これは、配列内の 1 つの要素 / ポイントする 1 つのメモリ アドレスのみを宣言したためです。次に例をいくつか示します。

char* x;
/* Allocate 6 bytes of memory for me and point x to the first of them. */
x = (char*) malloc(6);
x[0] = 'H';
x[1] = 'e';
x[2] = 'l';
x[3] = 'l';
x[4] = 'o';
x[5] = '\0';
printf("String \"%s\" at address: %d\n", x, x);
/* Delete the allocation (reservation) of the memory. */
/* The char pointer x is still pointing to this address in memory though! */
free(x);
/* Same as malloc but here the allocated space is filled with null characters!*/
x = (char *) calloc(6, sizeof(x));
x[0] = 'H';
x[1] = 'e';
x[2] = 'l';
x[3] = 'l';
x[4] = 'o';
x[5] = '\0';
printf("String \"%s\" at address: %d\n", x, x);
/* And delete the allocation again... */
free(x);
/* We can set the size at declaration time as well */
char xx[6];
xx[0] = 'H';
xx[1] = 'e';
xx[2] = 'l';
xx[3] = 'l';
xx[4] = 'o';
xx[5] = '\0';
printf("String \"%s\" at address: %d\n", xx, xx);

割り当てられたメモリの free() を実行した後でも変数 x は使用できますが、その内容は不明であることに注意してください。また、2 回目のメモリ割り当てが最初の割り当てと同じスペースで実行されるという保証がないため、2 回の printf() で異なるアドレスが返される可能性があることに注意してください。

おすすめ記事