こんばんは、Cの初心者です宜しくお願いします。
Cでポインタの記述を良く見るのですが、色々と本とかサイトとかで調べましたが、ポインタを使うことのメリットとか、使う理由を書いてるものに巡り合いません。
一体何故ポインタというものがあるのでしょうか。
変数(アドレス)を参照する事で、メモリの節約とか動作が速くなるとか、そのようなものが主な理由でしょうか。
逆にポインタを使わないと書けないプログラムとかはあるのでしょうか。
関数は、ポインタを引き数として元から設計されているので仕方がないとしても、、、、、、
以上初心者としての非常に素朴な疑問です、宜しくお願いします。
No.3ベストアンサー
- 回答日時:
お疲れ様です。
>>関数は、ポインタを引き数として元から設計されているので仕方がないとしても、、、、、、
意味が分かりません。
私が今まで勉強して来た観点から見て以下を挙げます。
まず、C言語で挙げれる利点として
(1)文字列操作の簡素化
(2)自己参照構造体とメモリ動的確保による可変長データの操作
(3)標準的な関数として用意されているqsort等へ渡す関数へのポインタ
(4)構造体などの大きなデータを別関数へ渡す際のスタック領域節約かつ高速化
そして、C++で挙げれる利点として
(1)継承クラスのインスタンスのポインタを親クラスのポインタへ格納する事によるポリモーフィズムの実現
他にもあるかもしれませんが、私は上記しか知りません。
>>関数は、ポインタを引き数として元から設計されているので仕方がないとしても、、、、、、
意味が分かりません。
#関数の引数がポインタ型をしていされていということですが。
多分そんな関数があったような。
No.10
- 回答日時:
1.処理の高速化。
関数に引数を渡す時はコピーが必要です。例えば10Mbyteものデータをコピーするのはとても時間がかかります。構造体を引数にすることを考えてください。構造体のデータを渡すのには時間がかかりますが、ポインタを使えばアドレスだけを渡すので時間が少なくてすみます。
2.デバイスドライバを書く時に必須となる。
デバイスドライバ等では、決められたアドレス(ハードウェア等の設計に依存)にアクセスしてプログラムを実装する必要があります。このようなプログラムを書く場合はポインタのようにアドレスを指定してアクセスする機能が必須となります。
その他、プログラム上の都合でポインタは便利と感じることがたくさんあります。ポインタは最初はわかりにくいのはそうなのですが、実際に使っていくことでその便利さが実感できると思います。
皆さん、多数の貴重なご回答有り難うございます、大変勉強になりました。
やはり初心者にとってはポインタはかなりハードルが高いのですが、
皆さんのご意見で励みになりました、もっともっと勉強して苦手意識をかえていきます。
今後とも宜しくお願いします。
No.9
- 回答日時:
>ポインタを使用する理由
C言語のローカル変数はスタック上に作成されます。
で、関数コールを行う際は引数をスタック上において(コピーして)から実行します。
呼ばれた関数は呼ばれる直前にコピーされたものを引数として使用するため、
その値を変更しても呼び出し元にリターンした際は消えてしまうことになります。
これでは返値だけでしか値を返せないことになります。
scanf()等のように、一つの関数で複数の変数に値を返したい場合は
ポインタを使用した値の受け渡しは必須になります。
またeiji_0035さんも質問の中にかかれていますが、引数に大きな構造体を
渡そうとすると、それ全てをスタック上にコピーすることになります。
これもポインタを使用すると アドレス指定に必要なサイズ(4~8バイト程度)で
済むことになり、効率的になります。
>逆にポインタを使わないと書けないプログラムとかはあるのでしょうか。
一つの関数で複数の値を書き換えるには先に述べたようにポインタが
必須です。
逃げ道としてはグローバル変数を使用....なんてこともできますが、
変数引き渡しがうまくできないから....が理由では邪道です。
大規模なプログラムになればなるほどバグを生む原因になります。
あと普通は使用しませんが、関数もポインタに割り当てることができ、
そのポインタを使用して動的に関数を実行したりすることができます。
複数の関数をポインタの配列に定義することで、配列要素で使用する関数を
変更する、なんてこともできます。
「関数ポインタ 配列」で検索するといろいろ出てくるかと思います。
No.8
- 回答日時:
>一体何故ポインタというものがあるのでしょうか。
Cの前身のBでポインタが使われていたからです。
Cは、アセンブラでUNIXを開発していたケン・トンプソンが、開発労力を減らすために開発したBが遅くて使えなかったため、見かねた同僚のデニス・リッチーが、ケン・トンプソンのために、Bを修正するところからスタートした言語です。
昔はメモリが物凄く高価であり、かつCPUも遅かったため、如何に少ないメモリで高速にプログラムを動作させるかが課題であった訳です。
http://cm.bell-labs.com/cm/cs/who/dmr/kbman.html
No.7
- 回答日時:
>データー構造をリスト型にする(あるいはツリー構造にする)とかは、
>そもそも、ユーザー(プログラマ)が指定できるものでしょうか。
ある問題をプログラムで解決するとき、
どのようなデータ構造(やアルゴリズム)を用いるか、
事前に吟味する必要があります。
配列を使えば解決できるのか、他のデータ構造でないとダメなのか、
といった具合です。
吟味の結果、例えばリスト構造が最適であると判断したとき、
その構造を「自分で」考えます。
だれかがいつの間にか作ってくれているわけではありません。
>(プログラムの書き方でそのようなデーター構造ができる?)
発想が逆です。
適切なデータ構造(とアルゴリズム)をもとに、プログラムを書きます。
asuncionさん、回答有り難うございます。
>適切なデータ構造(とアルゴリズム)をもとに、プログラムを書きます。
#具体的に例えばこのようなデータ構造にしたい場合には、このようにプログラムをかくとか紹介しているサイトとかはあるのでしょうか。
探したんですが、データ構造の解説をしているサイトは山ほどあるのですが、このようにして、プログラムを書くとうサイトが見つからないのですが。
No.5
- 回答日時:
概念的で、申し訳ないです・・・。
> 変数(アドレス)を参照する事で、メモリの節約とか動作が速くなるとか、
> そのようなものが主な理由でしょうか。
おっしゃるとおり、効率的なプログラムが一番の理由だと思いますよ。
Cで書かれたソースはコンパイルを経てアセンブラに近い形に変化していきます。アセンブラ・コードのほとんどが、メモリから読み出し、計算や加工を施し、メモリに格納します。この時、メモリサイズやアドレスやらを考慮した書き方をすると、高速かつ効率的なアセンブラ・コードを吐き出してくれます。そのメモリサイズやアドレスやらを表現するのに必要な機構がポインタとなります。C言語が可読性が高い、低級レベルの言語と言われるゆえんでは無いかと、僕は考えます。
組み込み型の機器に搭載するプログラムもCで書かれる時代ですが、高効率なコードを生成しなければならない場合、可読性を犠牲にしてでも、ポインタを使ったトリッキーなコードをよく見てきました。
あるメモリ領域を0埋めしていくコードを考えてみたとき、下記のようなプログラムが書けそうです。func1はポインタを使っていません。func2はポインタを使っています。
---------- ここから ----------
static int buf[256];
void func1(void) {
int i;
for( i=0 ; i<256 ; i++ ) buf[i] = 0;
}
void func2(void) {
int *p;
p = buf;
for( i=0 ; i<256 ; i++ ) *p++ = 0;
}
---------- ここまで ----------
最近のコンパイラは非常に優秀ですし、CPU自体の性能が高く、高効率のアセンブラ・コードをはいてきます。しかしながら、おそらくfunc2の方がコードの長さ、コードの実行スピード共に優れていると思われます。
ここから先はアセンブラコードやCPUの知識が必要になります。buf[i]=0というのは、bufが指すアドレスを示す箱(レジスタと呼びます)の値に、その位置を示すiの値を入れる箱の値を毎回足して、0を保管すべきアドレスを計算します。このアドレスに0を保管します。これに対し、*p++=0は、アドレスを入れる箱(レジスタと呼びます)にます、その先頭アドレスを入れておきます。その指し示すアドレスに0を格納して、アドレスを定数分増加させます。似ている様に感じますが、多くのCPUやコンパイラで*p++=0が楽に処理できるでしょう。
C言語のもっとも特筆すべき特徴がポインタであると考えています。ポインタを使う事で可読性が悪くなったり、逆にまどろっこしくなったりする事もありますから、好みに合わせて使えればいいと思います。
No.4
- 回答日時:
最も大きなメリットは高級言語でありながらアドレスが扱えることですね。
アセンブラではアドレスが扱えて当然なのですが。
具体的な例としてはA,B,Cという別々の構造体とポインタPに関連付けられたXという構造体を
ダイナミックに重ねて一律にXという構造体としてで扱えるということです。
つまり、A,B,Cのいずれかの先頭アドレスをPに代入すればそれぞれのエリアがその時々で
Xというひとつの構造体で扱えるということです。
リスト構造が書きやすいというのもそれが理由です。
あとC言語ではポインターの演算ができますので実行時間の短いプログラムが書けます。
余談ですが、
1.C言語はOSのUNIXを書くために作られたのでアドレスやアドレス計算はできて当たり前なのです。
2.ポインターは難しいのでC言語の習得に苦労します。
元々CはOSを書くようなプロが使う言語でしたから。
エラーチェックやエラーメッセージが極端に不親切なのもそれが関係しています。
ちなみにCから派生したJAVAにはポインターが有りません。
No.1
- 回答日時:
色々メリットはあると思いますが…。
まずプログラムを組んでいて初めに出てきそうなのが「参照渡し」ではないでしょうか。
複数の値を関数から受け取りたい場合どうするかとなると、手っ取り早く変数の参照渡しをして値を受け取る事になると思います。
あとは…勉強としてポインタの概念を理解すると、コンピュータの基礎を理解できる…かもしれません。
上記は一例で色々あると思いますが、あとは他の方におまかせします。
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
関連するカテゴリからQ&Aを探す
おすすめ情報
- ・漫画をレンタルでお得に読める!
- ・14歳の自分に衝撃の事実を告げてください
- ・架空の映画のネタバレレビュー
- ・「お昼の放送」の思い出
- ・昨日見た夢を教えて下さい
- ・【お題】絵本のタイトル
- ・【大喜利】世界最古のコンビニについて知ってる事を教えてください【投稿~10/10(木)】
- ・メモのコツを教えてください!
- ・CDの保有枚数を教えてください
- ・ホテルを選ぶとき、これだけは譲れない条件TOP3は?
- ・家・車以外で、人生で一番奮発した買い物
- ・人生最悪の忘れ物
- ・【コナン30周年】嘘でしょ!?と思った○○周年を教えて【ハルヒ20周年】
- ・ハマっている「お菓子」を教えて!
- ・最近、いつ泣きましたか?
- ・夏が終わったと感じる瞬間って、どんな時?
- ・10秒目をつむったら…
- ・人生のプチ美学を教えてください!!
- ・あなたの習慣について教えてください!!
- ・牛、豚、鶏、どれか一つ食べられなくなるとしたら?
- ・都道府県穴埋めゲーム
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
セグメントエラー
-
C言語のポインタに直接アドレス...
-
init関数の意味
-
デバイスハンドルとは?
-
LPSTR型の初期化について
-
ExcelVBAでのkernel32(64bit)
-
CWnd::EnableWindow()の扱い方
-
c言語で任意のファイルから読み...
-
メモリのアドレスからの値の取...
-
[C言語] NULLは必ず0(番地)です...
-
C言語でのconstを返す関数
-
NULLポインタが0でない処理系と...
-
C言語の文字列?処理 strcpyやl...
-
C++で変数の型を途中で切り替え...
-
ハンドルはポインタか
-
ポインタの結合に関する質問です
-
Run-Time Check Failure #3とい...
-
構造体とfscanf
-
不適切なポインタ
-
プロトタイプ宣言について
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
C言語のポインタに直接アドレス...
-
セグメントエラー
-
init関数の意味
-
fopne で失敗する原因
-
Run-Time Check Failure #3とい...
-
戻り値で構造体を返すことは可...
-
ExcelVBAでのkernel32(64bit)
-
LPSTR型の初期化について
-
参照型で受け取った引数をポイ...
-
C言語でのconstを返す関数
-
ハンドルはポインタか
-
ハンドル、アドレス、ポインタ...
-
PASCALとFARの意味
-
CWnd::EnableWindow()の扱い方
-
ポインタについて
-
デバイスハンドルとは?
-
C言語の文字列?処理 strcpyやl...
-
ポインタのミスでOS壊れるの...
-
C++ vectorのbeginについて
-
基本アルゴリズムの『返す』の...
おすすめ情報