• 締切済み

C言語のポインタのどのあたりが難しいと思いますか?

C言語のポインタは初心者にとって大きな壁であるとよく言われます。 具体的にポインタのどのあたりが難しいと思いますか? 経験者の方、初心者の方などいろんな意見をお聞かせください。 ちなみに私もポインタでつまづいた人間の一人です。 つまづいた箇所は一箇所ではないのですが、例を挙げるなら int *p; p = &a; *p = a; で pと *pの違いがわからなかったですね…。\0とNULLの違いもごっちゃになっていましたし。 似たような表記だけど意味は違う、という箇所にひっかかっていました。 ポインタがどのようなものなのかというイメージは理解しやすかったのですが…。

  • nekoc
  • お礼率94% (128/135)

みんなの回答

  • galluda
  • ベストアンサー率35% (440/1242)
回答No.5

がると申します。 本人は躓いたことはまったくないのですが、躓いてる人は多々拝見しています。 躓く方の多くは、ある程度「上澄みだけ」を学ばれている方に多いように思います。 直接的に書くと「頭の中でメモリイメージが持てるか否か」がおおよそ分かれ目であるようです。 イメージが出来ればポインタもわかるし、逆もまたしかり。 書式は私もしょっちゅう忘れますが(笑)、書式だけなら、それこそ小さなメモが一つあれば思い出せるので。 ただ、概念を理解するしないは、致命的な差異になってしまいます。 個人的には。やはり「一度はマシン語やっとけ」って思ってしまいます。 まぁ…あんまりマシン語とかやり過ぎると、オブジェクト指向で引っかかる人も少なくないのですが(苦笑 慣れればどっちも簡単なんですがねぇ。 以上、年齢いったおっちゃんの戯言です。

nekoc
質問者

お礼

>「頭の中でメモリイメージが持てるか否か」 まさにこれだと思います。 アドレスとポインタ、ポインタの型、ポインタの意味etcのイメージを整理するのに図に書こうとしたのですが、 最初はまったく書けませんでした。 ポインタが何を指すのか、指すとはどういうことなのか。 具体的な形にまとまるには時間がかかりました… >慣れればどっちも簡単なんですがねぇ。 きっちり概念を理解できるかが鍵ですね。

  • koko_u_
  • ベストアンサー率18% (459/2509)
回答No.4

関数ポインタの宣言などほとんど暗号ですな。 ポインタの概念が原始的なため、ソースコードと、それが実現しようとしている意図との間に距離があることが難易度を高めていると思います。 # ぱっと見て、何をしようとしているのかが分からない 他にポインタ絡みで言えば、動的に確保した領域を開放し忘れたり、逆に開放済みの領域を再度開放してしまったり、非常にナイーブな所までプログラマが面倒を見なければならない所かな。 というわけで、もっぱら C++ で書いてます。 # 関数ポインタは関数オブジェクトで、 # 動的な領域を確保したら取りあえず auto_ptr につっこんでます。

nekoc
質問者

お礼

ご回答ありがとうございます。 >ぱっと見て、何をしようとしているのかが分からない 私も似たようなことを感じました。 何かを指しているんだろうなあとまではイメージできたのですが、だから何?何でそんなことをするの? と思っていました。

  • 5S6
  • ベストアンサー率29% (675/2291)
回答No.3

別に難しいとは思いません。 ポインタはアドレスを指すのであって本体ではない。 ポインタでないものは&をつけることによりアドレスを指す。 と言うだけです。 \0は文字列終わりを差しNULLは何もない。 と覚えれば簡単です。 ポインタのポインタとかもあるけど既にポインタを使った プログラムなんて学生の勉強用ぐらいにしか使いません。 ただし非常に速度重視プログラム、ハッカーなどになりたい場合は 必要ですね。 スタックオーバーフローってどんなの?とか。

nekoc
質問者

お礼

ご回答ありがとうございます。 >ポインタはアドレスを指すのであって本体ではない。 >ポインタでないものは&をつけることによりアドレスを指す。 シンプルにまとめるならそうなると思いますし、ある程度ポインタを理解した今ならその言葉の意味がわかるような気がします。 ただ、ポインタに触り始めたころは 「ポインタはアドレスを指すのであって本体ではない。」ってどういうこと?本体って?指すって?? 「\0は文字列終わりを差しNULLは何もない。」って?何もない??\0はヌル文字じゃないの?ヌルなのに違うの?? のように、 メモリ上のポインタの動きや単語の意味が全然イメージできていなかったです。 お恥ずかしい限りです。 ポインタという概念自体が全くの未知のものだったので混乱していたんでしょうね。

noname#32786
noname#32786
回答No.2

大分前にCでプログラム書いてましたが、本当に苦手で、ポインタも あいまいに覚えていたので、ダンプで中身を確認して結果的に動けばOKみたいな感じでした。 文字列のコピーとか配列のコピーとか、文字列操作でインクリメントした時の中身とか、最終的に理解できてなかったと思います。 Javaに慣れてしまった今は細かいことなど、あとかたもなく忘れました。

nekoc
質問者

お礼

ご回答ありがとうございます。 >あいまいに覚えていたので、ダンプで中身を確認して結果的に動けばOKみたいな感じでした。 ポインタに限った話ではありませんが、私もどうしてそうなるのかよくわからないけど動いたからいいや!という時があります。 本当はきちんと理解しておいた方がいいってわかっているんですけどね… 配列に限らず、ポインタは構造体など他のものにからむとややこしくなるように思います。

回答No.1

僕もC言語は挫折した派です。 FORTLANやBASICからですと分かりにくいですね。 アセンブラを学ぶと分かりやすいのですが、C言語では、ポインタのポインタが使えるので、ここで撃沈しましたねぇ。 FORTLANやBASICで配列に、どっぶり漬かってしまったので(FORTLANなら5次元以上でもOKでしたが、、)、文字列をポインタで扱うのが習得できませんでした。それから文字列の終了の記述ですね。

nekoc
質問者

お礼

ご回答ありがとうございます。 文字列をポインタで扱う…ということは配列のポインタですよね。 私は先頭アドレスを理解するのに時間がかかりました。 というか、C以外の言語は勉強したことがないのでFORTLANやBASICの方がわからなかったりします(汗)

関連するQ&A

  • C言語のポインタについて教えてください。

    C言語のポインタについて教えてください。 ・pointer1.c  int main(){   int a;   int *p;   p = &a;     a = 123;   printf("%d", *p);   return 0;  } ・pointer2.c   int main(){ int a[100]; int *p; p = &a[0]; int i; for(i = 0; i < 100; i++) a[i] = i; for(i = 0; i < 100; i++) printf("%d", *p++); return 0; } と二つのソースコードがあるとき、pointer2.cの「p = &a[0]」をpointer1.cのように「p = &a」と書けないのはなぜですか?  また、「&a」は動かすことのできなく、「aを指し示す*p」は動かすことができる変数のようなもの、という認識に誤りはないでしょうか?  宜しくお願いします。

  • C++言語のポインタについて

    現在、C++言語を学習しているのですが、 ポインタを使わない、 int main() { Human human; human.Introduction(); } と、ポインタを使った、 int main() { Human *p; p = new Human; p->Introduction(); delete p; } があります。どちらも同じ動作をしますが、ポインタを使ったものがよく使われているのは、 メモリの節約?動作速度?のためなのでしょうか? なぜ使われるのか教えてください。

  • NULLポインタは0と書かなければだめ?

    C++言語を使っています。 C++言語でNULLポインタを表す場合、0やNULLを使用しますが、 「NULLは単なるマクロなので本来は0を使わなければだめ」という話を聞きました。 つまり、 int *p = 0; が本当の正しいNULLポインタであり、 int *p = NULL; は推奨されていない(?)NULLポインタというようです。 今まであまり疑うことなく、NULLポインタを表すのにNULLを使用していましたが、 上記の内容は本当でしょうか。

  • 【C言語】別関数でポインタの値を変えたのに変わらない。

    【C言語】別関数でポインタの値を変えたのに変わらない。 メイン関数のポインタの値を、別関数で書き換えるプログラムを作りました。 以下がそのプログラムになります。 そのままだと、ダブルポインタを操作する必要があるので分かり辛いです。なので、ダブルポインタをシングルポインタにしてからポインタの書き換えを行うようにしました。その結果、きちんとポインタの書き換えが出来なくなってしまいました。 なぜ出来なくなってしまったのでしょうか。 2つのプログラムの違いは、 >  *pp = &dummy; が >  p = *pp;      // ダブルポインタをシングルポインタにした >  p = &dummy; に変わっただけです。 【参考】http://www.kouno.jp/home/c_faq/c4.html#8 -----------------正しいプログラム---------------- // 以下プログラムは、正しく動作する // 実行結果は、 //   p = 5 // と表示される void func( int **pp ); int main (void){   int *p;   int a = 0;   p = &a;   func( &p );   printf("p = %d\n", *p);   return 0; } void func( int **pp ){   static int dummy = 5;   *pp = &dummy; } ---------------------------------------------- -----------------間違いプログラム---------------- // 以下プログラムは、正しく動作しない // 実行結果は、 //   p = 0 // と表示される void func( int **pp ); int main (void){   int *p;   int a = 0;   p = &a;   func( &p );   printf("p = %d\n", *p);   return 0; } void func( int **pp ){   static int dummy = 5;   int *p;   p = *pp;      // ダブルポインタをシングルポインタにした   p = &dummy; } ----------------------------------------

  • C言語(またはC++言語)についての質問です。

    C言語(またはC++言語)において、以下の変数x、ポインタ変数(*p,**pp, ***ppp)のメモリ上のイメージを記述しなさい。 int x, *p, **pp, ***ppp; x=10; p=&x; pp=&p; pppp=&pp; という問題なのですが、わからなくて困っています。 このプログラムはどのようなものなのでしょうか。 詳しい回答をよろしくお願いします。

  • C言語のポインタについての質問です。

    C言語のポインタについての質問です。 2つのプログラムを作り、片方で数値を入力し、 もう片方でその数値を読み取りたいと思っています。 数値入力のプログラムは次のようになっています。 #include<stdio.h> void main(void){ int A=1; int *p; p=&A; printf("%p\n",p); } この実行結果は「0012FF88」となりました。 次にこの「0012FF88」というアドレスを使って「1」を読み取る 別のプログラムを作りたいと思っています。 #include<stdio.h> void main(void) { int add; int a; printf("アドレスは?\n"); scanf("%x",&add);    //「0012FF88」と入力 a=*(int*)add; printf("%x---->%d",&add,a); } このようなプログラムを作ってコンパイルできたのですが、 実行してアドレスを打ち込むと「Win32の例外が発生しました」 となって実行できません。 何かよい方法やプログラムの問題などありましたら 教えて頂けませんか?

  • JavaでC言語のポインタ演算風な使い方は

    Java初心者です。ずっとC言語をやっていました。 Javaにはポインタは存在せず(実際は参照渡しなのでポインタその ものなのですが)、ポインタに対する演算はありませんよね。 C言語で、 int buf[2*10]; int *dst = buf; for(i=0;i<10;i++){ dst[0]=a; dst[1]=b; dst += 2; } のようなソースをJavaで書こうとすると、 for(i=0;i<10;i++){ buf[i*2+0]=a; buf[i*2+1]=b; } しか思いつきません。 コンパイルして最適化されれば問題ないと思いますが、 なんか配列中の演算が演算量をとりそうで、気になっています。 もっと高速に処理されるような書き方はないものでしょうか? アドバイスよろしくお願いします。

    • ベストアンサー
    • Java
  • C言語、ポインタについて。

    C言語初心者です。"やさしいC"などの入門書を呼んでいて「ポインタ」につまづきました。 別書を買ったり、サイトを見たりしたのですが、理解できませんでした。 "やさしいC"からの引用なのですが、 正: #include <stdio.h> int add(int *x1,int *x2,int a); int main (void){ int n1,n2,a,ans; printf("2科目分の点数を入力してください。\n"); scanf("%d",&n1); scanf("%d",&n2); printf("加算する点数を入力して下さい。\n"); scanf("%d",&a); ans = add(&n1,&n2,a); printf("%d点加算しましたので\n",a); printf("科目1は%d点となりました。\n",n1); printf("科目2は%d点となりました。\n",n2); } int add(int *x1, int *x2,int a){ *x1+=a; *x2+=a; } 誤: #include <stdio.h> int add(int x1,int x2,int a); int main (void){ int n1,n2,a,ans; printf("2科目分の点数を入力してください。\n"); scanf("%d",&n1); scanf("%d",&n2); printf("加算する点数を入力して下さい。\n"); scanf("%d",&a); ans = add(n1,n2,a); printf("%d点加算しましたので\n",a); printf("科目1は%d点となりました。\n",n1); printf("科目2は%d点となりました。\n",n2); } int add(int x1, int x2,int a){ x1+=a; x2+=a; } この2つの違いはなんでしょうか。 アドレスか、そうでないか、という違いはわかりますが、なぜ"誤"のコードだと正しく処理されないのかがわかりません。 教えてください、お願いします。 (「やさしいC」の回答より引用)

  • C言語のプログラム(ポインタについて)

    /* コマンドライン引数で与えられた長い文字列を長さ10文字ずつに分割してp[100][11]に順番に入れ,表示するプログラム <例>./a.out 1234567890ABCDEFG p[1] = "1234567890" p[2] = "ABCDEFG" */ #include <stdio.h> int main(int argc, char **argv) { int i, len; char *str; len=0; for(i=1; i<argc; i++){ len += strlen(argv[i]); } if((str=(char *) malloc(len+1))==NULL){ perror("malloc"); exit(1); } strncpy(str,argv[1],10); for(i=2; i<argc; i++){ strcat(str,argv[i]); } printf("p[%d] = %s\n", i-1, str); } 上に示した処理をするプログラムを作成したいのですが、 今のソースは単に10文字表示するだけで、ここからどうしたらいいのか見当がつきません・・・・・。 なのでどういった改良をすればよいのか教えていただければ助かります。 /*配列aにファイルから値を読み込み、それを表示した後*/ /*配列に格納された値を下に1つずつずらして表示するプログラム(ポインタを使用して)を作成*/ /*(なお、一番上a[0]にはa[99]の値を入れる)*/ /*<例>*/ /*a[0] = 0 */ /*a[1] = 1 */ /*  ・ */ /*  ・ */ /*a[98] = 98*/ /*a[99] = 99*/ /*a[0] = 99 */ 1つずらしたもの /*a[1] = 0 */ /*  ・ */ /*  ・ */ /*a[98] = 97*/ /*a[99] = 98*/ (読み込むファイル[file-100.dat]には0~99の数字が1つずつ改行しながら入っています) できればこちらにも答えていただければ嬉しいです。 この問のソースは書きませんが、ファイルを配列に読み込んで表示してからの処理がいまいちわからず困っています。 すばやい御回答お待ちしております。よろしくお願いします。

  • C言語の配列とポインタについて

    C言語の配列とポインタについてわからないことがあります。 以下のソース例は、10個の値の平均値を求めるプログラムです。 コメントを挟んだ部分が疑問点です。 【ソース例】 #include <stdio.h> int getaverage(int *data); int main(void) { int average,array[10] = {15,78,98,15,98,85,17,35,42,15}; average = getaverage(array); printf("%d\n",average); return 0; } int getaverage(int *data) { int i,average = 0; for (i = 0;i < 10;i++) { average += data[i]; /*ポインタ変数なのに? */ } return average / 10; } 【実行例】 49 このdata[i]はポインタ変数であり、 配列arrayの i 番目の要素であるarray[i]の"アドレス" が代入されているはずだと思うのですが、 なぜ通常の整数変数であるaverageと数値計算が出来、正しい結果が出たのでしょうか? あたかもdata[i]には、 array[i]の"アドレス"ではなく、 array[i]の"メモリの中身"が代入されているようです。 どういうことでしょうか? 回答よろしくお願いします。