• ベストアンサー

配列とポインタの違いについて

書籍などで配列とポインタの違いについて勉強していますが、未だによくわかりません。 C言語における配列とポインタの違いについて教えて頂けますでしょうか?

質問者が選んだベストアンサー

  • ベストアンサー
  • S117
  • ベストアンサー率40% (18/45)
回答No.5

配列とポインタを厳密に説明するのはかなり面倒ですが、違いがよく分からないとのことなので、「違う部分」をいくつか上げますね。(動作検証はVisual C++ 2008 Express Edition) char ary[10]; char *ptr; で、変数を作ります。そして、 ary[0] = 'a'; ptr[0] = 'a'; 2行目はおそらく実行時エラーです。なぜなら、ポインター変数は単にポインターの入れ物なので、初期値は不定ですし、指す先も不正な領域で使用できないでしょう。しかし、 ptr = ary; こうすると、ptrはaryの先頭要素を指すようになり、ptr[0]もary[0]も同じ値になります。一方、 ptr = ptr + 1; /* OK */ ary = ary + 1; /* エラー */ です。なぜならaryはあくまでも配列であり、ポインターではないため、ポインタ値の変更はできません。Cの配列は式の中でのみ先頭要素のポインターとして評価されます。また、 char **pp = &ptr; /* OK */ char **pp2 = &ary; /* 警告(型の互換性) */ char(*pa)[10] = &ary; /* OK */ です。アドレス演算子(&)で使用される場合などで、配列は配列そのものとして扱われます。そして、配列は型に要素数を持ちます。 あとは、規格書にもっと細かいことが書いてあるはずです。(私のこれは参考URLを参考にして書きました。規格書が手元にないので……)

参考URL:
http://kmaebashi.com/programmer/pointer.html
masy0312
質問者

お礼

非常にわかりやすい説明ありがとうございます。 なんとか納得できました。

その他の回答 (5)

  • titokani
  • ベストアンサー率19% (341/1726)
回答No.6

本質的にまったく違うものです。 ただ、式中に配列名が現れた場合、暗黙のうちにポインタに変換されます(一部例外を除く)ので、そういった誤解の元になっています。

masy0312
質問者

お礼

ご回答ありがとうございました。

noname#29459
noname#29459
回答No.4

配列とは、値をいれるケースが、いくつかつづいたもの。 char a[MAX_T]; とは、aは、charをいれるケースが、MAX_T個つづく(配列)。a は、また、その先頭アドレスを意味する定数。この宣言によって、配列の領域が確保される。 ポインタとは、なにかしら、値が入っている場所を指し示すもの。 char *b; bは、charがはいっているケースのアドレスを保持する変数。 b = a; bに、aの値をいれる。 char **c; cは、char *をさすポインタ。だから、 c は、 char * 型をさしている。したがって、そのポインタをたぐれば、先には、char が入っている。

masy0312
質問者

お礼

ご回答ありがとうございます。 理解できました。

  • snowize
  • ベストアンサー率27% (68/245)
回答No.3

簡単に説明するのもいいですが、どちらかというと自信を持って説明できるくらいの知識を身につけてもらいたい箇所なので、柴田望洋さんのポインタ関係の著書をお薦めいたします。類書の中では最も理解しやすいかと存じます。 だいぶ昔なので自信がありませんが、恐らく『秘伝C言語問答 ポインタ編』で間違いないと思います(長すぎて参考URL載せられませんでした)。ポインタと配列の違いについても丁寧に説明されていましたし、「ポインタのポインタ」なんていう「?」な用語にも分かりやすい説明をつけてくれてあります。

masy0312
質問者

お礼

ご紹介にございました書籍をさっそく参考にさせて頂いております。 ありがとうございました。

  • g_liar
  • ベストアンサー率52% (382/728)
回答No.2

配列やポインタは、メモリとの関係がわかると一気に理解が進むのですけどねぇ…。 配列は、実体。 ポインタは、実体を指し示すものです。 以下のページが参考にならないかなぁ? http://www9.plala.or.jp/sgwr-t/c/sec10-3.html

masy0312
質問者

お礼

ご回答ありがとうございました。

  • jacta
  • ベストアンサー率26% (845/3158)
回答No.1

質問者さんはどのように理解していますか? ご自分の言葉で、配列とポインタの違いを説明してみてください。 それに対して、合っている、あるいは間違っているということを指摘した方が、適切な回答になるかと思います。

masy0312
質問者

お礼

配列とは、指定した型のサイズで値を格納するための複数の箱を メモリに連続して確保したものであり、 ポインタとは、ある型のオブジェクトが存在するメモリのアドレスを 値としてもつもの、という解釈です。 わかりにくい説明で申し訳ございません。。。

関連するQ&A

  • 「配列名はポインタ」という表現は間違っているのでは?

    よくネット上で、「配列名はポインタ」というような表現が出てきますが、 「配列名はポインタになっているのである。 http://www.wakhok.ac.jp/~kanayama/C/99/node111.html」 このような表現は、間違っているのではないでしょうか? C言語を作った本人によるK&Rのp.121には、次のように書かれています。 配列名とポインタの間には、心に留めておかなければならない違いが一つある。 ポインタは変数であり、したがってpa=aやpa++は意味のある演算である。   ←(1) しかし配列名は変数ではない。したがって、a=paやa++のような構文は正しくない。 ←(2) (1)より、 ポインタは、変数である ので、この対偶をとると、 変数でないものは、ポインタではない  ←(3) となります。 (2)より、 配列名は、変数ではない  ←(4) となるので、 (3)と(4)から、 配列名は、ポインタではない ←(5) となります。 そうすると、「配列名はポインタ」というような表現は間違っていることになり、誤解の元になるので、改めるべきではないかと思うのですが。

  • C言語 ポインタと配列

    C言語で配列をあつかう場合、ポインタをつかうか、配列の添え字を使って処理するか迷うのですが、どちらが良いのでしょうか? 処理速度ではどちらが上でしょうか?

  • 配列とポインタ

    配列とポインタの違いを教えて下さい。 後 char str[100]; と const char *strはどこが違いますか?

  • 関数へのポインタ渡しでの配列の初期化について

    はじめまして、C言語の基本的な質問をさせてください。 C言語で、外部関数へポインタで引数を渡す場合に、 関数に渡されるのはアドレスですよね? で、渡された関数側でそのポインタの配列の初期化を するときにはアドレスだけの情報だと、要素数がいくつ あるか分からず、領域の破壊をしてしまいそうな気が するのですが?いかがでしょうか? また、関数かなんかで、配列の要素数が分かる関数が あったような気がするのですが、それもアドレスだけ でわかるのでしょうか?

  • C言語 ポインタと配列の違いが理解できません。

    ポインタと配列の違いとは何でしょうか? 自分は学校で習ったのですがあまり深くはやってくれず良く理解していないままです。 ・ポインタと配列はしまう場所は同じなのでしょうか? ・単にしまい方、呼び出し方が違うだけなのでしょうか? ・ポインタと使えるところでは配列も使えるのでしょうか? ・そもそもしまわれる場所って何処なのでしょうか? 基礎中の基礎のことなので申し訳ないですが教えてください。 後、「」←このサイト見ろ だけのような解答は無しでお願いします。

  • 配列のポインタ配列のポインタから元の配列を参照する方法について

    C初心者です。下記の様に配列のポインタ配列を作って、そのポインタ配列のポインタを返すコードを書いて、main関数で元の配列の値を参照したいのですが、上手く参照できずに困っています。下記のコードの問題点も含めて、配列のポインタ配列のポインタから、元の配列の値を参照する方法を教えてください。お願い致します。 short int *motion_data(void) { short int data1[5][7] = { {2377,2174,0,0,0,0,0}, {2377,2377,2784,2648,2648,2648,2377}, {2377,2377,2784,2648,2648,2648,2377}, {2377,2377,2377,2377,2377,0,0}, {2377,2377,2377,2377,2377,0,0}, }; short int data2[5][7] = { {2377,2174,0,0,0,0,0}, {2377,2377,2919,2784,2784,2784,2377}, {2377,2377,2919,2784,2784,2784,2377}, {2377,2377,2377,2377,2377,0,0}, {2377,2377,2377,2377,2377,0,0}, }; short int *po_data[2]; po_data[0] = data1[0]; po_data[1] = data2[0]; return *po_data; }

  • ポインタ

    C言語で、 int c[6]と配列を作って、 ポインタでc[100]を指定すると、COREがでますよね? これをやると、コンピュータがフリーズする場合があるのですがなぜですか?

  • 配列のポインタについて

    先程はありがとうございました もうひとつ今日中に解決しておきたいことがあります ポインタを配列にするのであれば意味がわかるのですが、配列をポインタにすることに何のメリットがあるのでしょうか(もちろん可能ですが・・・) よろしくお願いします

  • ポインタ配列の動的確保

    ポインタの配列の動的確保について教えてください。 入力した数値をポインタ配列に入れるプログラムです。 下記のように書いてみました。(見づらくてごめんなさい) #include<stdio.h> #include<stdlib.h> #define kensu 3 main() { char abc[kensu+1]={'A','B','C','\0'}; char *ptr[kensu]; int i; printf("3つの整数を入力して下さい。\n"); for(i=0;i<kensu;i++){ ptr[i]=(char*)malloc(sizeof(char)*10); if(ptr[i]==NULL){ printf("メモリの取得に失敗しました"); exit(1); } printf("整数%c:",abc[i]); fgets(ptr[i],10,stdin); if(ptr[i][strlen(ptr[i])-1]=='\n') ptr[i][strlen(ptr[i])-1]='\0'; } for(i=0;i<kensu;i++) free(ptr[i]); } ちゃんと動いているようです。 しかし、ポインタ配列の動的確保をネットで調べてみると、ポインタのポインタ(?)を使って、下記のように2度mallocしています。 #include <stdio.h> #include <stdlib.h> #define N 3 int main(void) { char** arr; int i,j; arr = (char**)malloc(N * sizeof(char*)); /* ポインタ配列を確保 */ /* 配列の要素それぞれにつき、メモリ領域を確保 */ for(i=0;i<N;i++) arr[i] = (char*)malloc(N * sizeof(char));   ・・・ ポインタの配列を宣言して、配列の各要素に動的確保するのと ポインタのポインタを宣言し、ポインタ配列を動的確保して、再度配列の要素に動的確保するのとでは、何か違いがあるのでしょうか? ポインタのポインタを宣言し、ポインタ配列を確保する必要性が良く分かっていないのです。 ネット等で調べて見たのですが、理解力がないのかよく分かりませんでした。 どうか教えてください。

  • 配列表現とポインタ表現

    配列とポインタの2通りの表現で表せる場面によく遭遇します。例えば、pというdouble型の配列に乱数を10個発生させて格納したい時など、 for(i=0;i<10;i++) *(p+i) = (double) rand(); for(i=0; i<10; i++) p[i] = (double) rand(); のように、配列とポインタの2通りの表現が考えられると思いますが、複雑な場合などは特に、見た感じは配列のほうが分かりやすいと思います。 まだ、C言語の初級から中級向けの本しか読んでいないのですが、標準関数の多くがポインタを引数や返り値としていることを知りました。わざわざポインタ表現にすることの意義は、実行速度が上がることと、標準関数の多くがポインタを引数や返り値としているからと理解して良いのでしょうか。

専門家に質問してみよう