質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

Q&A

解決済

7回答

22826閲覧

ポインタの使い時ってどんな時ですか?

退会済みユーザー

退会済みユーザー

総合スコア0

C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

0グッド

7クリップ

投稿2015/10/18 03:12

編集2015/10/18 04:31

ポインタを使う時がわかりません
いろんなところで使えるとは、聞いたことがありますが、例えばどんなプログラムを使う時なんですか?

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答7

0

ベストアンサー

  • 配列や構造体を関数に渡す場合に、値で渡してしまうと、別のメモリー領域にコピーする無駄が発生します。ポインターで渡すと、ポインターだけがコピーされて無駄が無くなります。C言語ではほとんどの場合、配列や構造体はポインターで渡します。

  • 関数の結果を、戻り値以外で取得したい場合。呼び出し側で配列や構造体のメモリー領域を確保しておき、関数側ではその領域に書き込むと、戻り値を返さなくても結果を呼び出し元に渡すことができます。

  • scanfのように可変長のパラメーターに対して結果を返したい場合、可変長の戻り値というのは無いので、ポインターで渡します。

  • 関数をパラメーターにしたい場合、関数ポインターとして渡すことができます。

  • コンパイル時にサイズが決まっていない配列を使う場合は、malloc関数などによる動的なメモリーの確保を行います。その場合、確保した領域の参照先のポインターが返されます。

投稿2015/10/18 07:54

argius

総合スコア9388

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

退会済みユーザー

退会済みユーザー

2015/10/18 13:44

ありがとうございました
guest

0

いろいろです(^^;

一番よく使うのは、配列や構造体を関数に渡すときですかね。
普通の文字列も配列ですから、文字列を関数に渡すときもポインタを使います。

実体を渡すと、変数を渡された先の関数でもメモリ領域が必要なので、無駄になります。
ポインタを渡して参照させれば、その領域は必要ありません。

投稿2015/10/18 05:54

haraken

総合スコア70

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

退会済みユーザー

退会済みユーザー

2015/10/18 13:45

ありがとうございました
guest

0

例えば,foo45さんの挙げていたソースの中で,scanf("%d", &num);っていう関数ありますよね.
これなんかはまさに,ポインタを使ってscanf関数が実装されているということです.
この関数内ではnumという変数用の領域が確保されたアドレスに,32ビット幅の整数が書き込まれます.
ポインタを使わないとそんなことはできません.

c

1#include <stdio.h> 2void assign1(int *num, int val) 3{ 4 *num = val; 5} 6void assign2(int num, int val) 7{ 8 num = val; 9} 10int main(int argc, char *argv[]) 11{ 12 int num1 = 0, num2 = 0; 13 assign1(&num1, 5); 14 assign2(num2, 3); 15 printf("num1 = %d, num2 = %d\n", num1, num2); 16 return 0; 17}

こんな例で試していただければわかりますが,
値渡しと参照渡し(C言語ではポインタを使用)では全然意味が違います.

関数の返り値を2つ以上にしたい場合にもポインタは有用です.
returnでは2つの値を返すことはできません.(構造体を返すという例外はありますが)
その場合は引数にポインタをもらっておいてそれらに書き込むやり方が主流だろうと思います.
C言語で書かれたオープンソースOSであるLinuxはポインタだらけです.

投稿2015/10/18 06:26

KenTerada

総合スコア751

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

退会済みユーザー

退会済みユーザー

2015/10/18 13:44

ありがとうございました!
guest

0

使いどころは想像以上に多いので、この回答欄で手短に説明するのは困難ですが・・・
一言で言えば データの保存場所を意識した方が都合が良い場合 となります。

どういうことかというと、そもそも ポインタ変数 ではない、通常の変数 がどういうものかを振り返ってみれば分かります。

現在主流のノイマン型コンピュータは、どこまで進歩しても メモリ上の特定のアドレスCPU の間でデータをやり取りしながら処理を進めるという基本原理は変わりません。

しかし、人間が常にメモリ上のアドレスを意識しながらプログラムを書くのはしんどいので、プログラミング言語の 変数 が登場しました。つまり、人間にとって分かりやすい名前を自由に付けることができて メモリ上のアドレスを意識することなく アクセスできる、というのが変数を使う意義です。

通常は変数だけで事足りるのですが、メモリ上での データの格納場所 もしくは データの並び順 を気に掛けてプログライミングした方が、

  • 高速化できる
  • メモリを節約できる
  • 実装が簡単になる
  • 特定のアドレスに意図的にアクセスする必要がある

などの場合に ポインタ型変数 を使用します。ポインタ型変数の素晴らしい点は、一般的な変数と同様、人間にとって分かりやすい自由な名前を使用しつつメモリ上の特定の位置へアクセス出来るという点です。

さて、前半の幾つかについては、下記のようなとても分かりやすい解説が既にありますので、そちらをご参照ください。
C 言語にポインタがある理由は省メモリ化・高速化・開発作業の省力化です
C言語のポインタを要点を絞って解説してみる

最後の「特定のアドレスに意図的にアクセスする必要がある」という点については、特に 組み込み系 の世界では日常的に発生する場面です。
これは、メモリマップドI/O と呼ばれる技術で、ハードウェア制御用のレジスタを通常のメモリ空間の特定アドレスに割り当てるというものです。
こうした技術は、通常のPCでも、たとえばハードウェアをコントロールするような場面(デバイスドライバの開発)で使用されており、結構身近なところで活躍しています。

以上、理解のご参考になれば幸いです。

投稿2015/10/18 07:46

pi-chan

総合スコア5936

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

退会済みユーザー

退会済みユーザー

2015/10/18 13:44

ありがとうございました!
guest

0

プリミティブ型という類、つまり基本的な単品の値(int, float, charのような)はその値が直接的に受け渡しされることが多いです。(変数への代入や関数の引数など)
この場合、値が都度新しい領域へコピーされます。

しかし構造体や配列などを用いてプリミティブな値を複合的に扱うと情報量が大きくなるので、その塊を変数への代入や関数の引数に渡す際などに都度コピーをすると効率が悪いです。

なのでその「情報の塊」が置いてある場所を受け渡しする方法がよく取られます。この場所を指すのがポインタです。

ちなみにプリミティブ型をポインタで指すこともできます。
これはコーディングを効率よく行うために行われたりします。

プリミティブ型を値渡しすることに関して効率はどうなのかと言いますと、ポインタというアドレス番地を表す数値もプリミティブ型1個分で、参照渡しであってもこちらコピーされることになるので結局はプリミティブ型1個分のコピーは避けられないからだと思います。

投稿2015/10/18 07:24

GeneralD

総合スコア40

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

退会済みユーザー

退会済みユーザー

2015/10/18 13:44

ありがとうございました!
guest

0

ポインタを使う目的は、
[1.] メモリの消費量を減らし、ディスクやCPUの負担を減らす。
[2.] 様々な場所で値を読めるようにする
の2点です。

例えば、1つのプログラムで3MBの同じ画像データを100回使うとします。

使う度にファイルから読み込んで違うメモリ位置に配置すれば、
メモリは300MB消費し、
300回のディスクから読み込みを行うコードを書き、
300回のファイルIO負担がディスクにかかり、
300回分のコピーに関わるCPU負荷がかかります。

これを、1回読み込んだデータをポインタ型でそれぞれから読み込んだ場合、
最初に読み込んだデータを全てのコードで参照するようになりますので、
メモリは3MB消費し、[1.]
300回の参照だけ行うコードを書き、[2.]
1回のファイルIO負担がディスクにかかり、[1.]
1回分のコピーに関わるCPU負担がかかります。[1.]

これがポインタを使う意義です。

投稿2015/10/18 05:33

SKYYFISH

総合スコア654

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

退会済みユーザー

退会済みユーザー

2015/10/18 13:45

ありがとうございました
guest

0

c

1#include <stdio.h> 2 3void show0(void); 4void show1(void); 5void show2(void); 6 7int main() { 8 void (*pM[3])(void); 9 int num; 10 11 pM[0] = show0; 12 pM[1] = show1; 13 pM[2] = show2; 14 15 printf("0:車, 1:レーシングカー, 2:飛行機"); 16 scanf("%d", &num); 17 18 if (0 <= num && num <= 2) 19 (*pM[num])(); 20 21 return 0; 22} 23 24void show0(void) { printf("車です"); }; 25void show1(void) { printf("レーシングカーです"); }; 26void show2(void) { printf("飛行機です"); };

例えばこのプログラムでは、ポインタを使わなかったらswitchやifなどで0~2番を条件分岐させる必要が出てくる。

投稿2015/10/18 04:57

foo45

総合スコア106

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

退会済みユーザー

退会済みユーザー

2015/10/18 13:45

ありがとうございました
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問