• ベストアンサー

C言語の初心者です。

ポインタについて教えてください。 #include <stdio.h> int main() { int *p,a[2],i=0; p=a; scanf("%d",p); printf("%d\n",*p); i++; scanf("%d",p+i); printf("%d\n",*(p+i)); return 0; } これは整数を入力して出力といった簡単なプログラムなのですが、こういうポインタの使いかたって普通はしないでしょうか・・?。ポインタは使わずにこういう場合は2次元配列とかで出すのが普通なのでしょうか? また、下のプログラムなのですが、上記のプログラムをただ単にキャラ型で試しただけなのですが、どうして実行時エラーがおこってしまうのでしょうか? printfのところの*nameの、*を抜くと実行時エラーはおこりません。しかし、上記の整数では*はつけたままでも エラーしません。 整数とキャラ型では何かちがうのでしょうか?? #include <stdio.h> int main() { char *name,a[10]; name=a; printf("入力---"); gets(name); printf("%s\n",*name); return 0; } 初心者特有の質問をしてしまって申しわけございません。でも、ずっと悩んでて、すこしずつでもポインタの本当の使いかたを知りたいとおもいまして、初期段階ではありますがどうしても解らなかったので質問させていただきました。 そういうものだから!以外でご説明いただける方がいらっしゃいましたら宜しくお願いいたします。

  • yuki22
  • お礼率83% (159/190)

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

  • ベストアンサー
  • m_mik
  • ベストアンサー率26% (31/117)
回答No.4

自分で他人に教えるときの方法で書いてみます。 (長文になってしまいました) まず上のプログラムについて… 上記のような使い方をする場合もあります。 基本的には配列で取得したものは配列でアクセスするように心がけたほうが良いと思います。 慣れてくると「どっちでもいいや」と言う風になりがちですが、最初からそのように考えないほうが良いと思います。 今回の場合には、2次元配列を用いていませんのでその質問については ? なのですが、基本的には作成したものへのアクセスは同じものを使用するということです。 下の質問に対して… まず、ポインタとは何かをきちんと捕まえましょう。 ポインタ=アドレスを入れる箱 と思ってください。 (これは、自分が他人に教えるときによく使う手です) 同じように、int型はintの値を入れる箱、char型はcharの値を入れる箱と言うように… また、ポインタに*をつけたときの動作はどうなりますか? ポインタで示されたアドレスの中身を指定することになります。 ---- 上のプログラムについて ---- int *p int型を扱うポインタ(箱)が1つアドレスPに用意されます。 int a[2] int型の数値を入れる箱が2つ連続してアドレスAに用意されます。 p=a; ポインタpのアドレスを配列aの先頭にします。 これは、別の書き方をすると p = &a[0]; となります。 これでpの箱の中身は A となります。 printf("%d\n",*p) %d:指定された数値を表示する。 このときは、ポインタpのアドレスの内容を表示しようとしますので、数値を表示します。 ---- 下のプログラムについて ---- printf("%s" , *name) %s:指定されたアドレスからの文字列を表示する。 *nameではポインタnameのアドレスの内容を表示しようとしますが、printfではアドレスからの文字列を表示しようとします。 このため、nameの内容をアドレスとして認識することになりおかしなアドレスが指定されたことになります。 アドレスを指定するのですから、*は必要ありません。 以上、お分かりになるでしょうか?

yuki22
質問者

お礼

配列で取得したものは配列でアクセス・・なるほどです。 上の内容はポインタとはこんなときでも経験豊富な方は使用するのかとな?とおもい、無理につかってみました。 小さなプログラムからでもポインタ使っていけば馴染めるとおもったのです。 丁寧な回答いただけて感謝いたします。 お返事ありがとうございました。

その他の回答 (4)

  • peko_pee
  • ベストアンサー率53% (45/84)
回答No.5

最初のポインタの使い方についてはやはりちょっと冗長な感じがします。 No.2の方の例のようにaを配列として素直に利用するか、配列の名前(ご質問の 例の場合は a です)はその配列の先頭要素へのポインタとして利用できるとい う規則を使って、 #include <stdio.h> int main() { int a[2],i=0; scanf("%d", a); printf("%d\n", *a); i++; scanf("%d", a+i); printf("%d\n", *(a+i)); return 0; } とすれば、pを使わずに済みすっきりします。 整数型とchar型は、表現できる数値の範囲に違いがあります。 unsigned(符号無し)型で説明しますと、 char型 0から255 int型 0から4294967295(32ビット版コンパイラの場合)     0から65535 (16ビット版コンパイラの場合) の整数を表現できます。文字列はchar型の数値の並び(配列)という形で利用し ます。 上記の型の違いともちょっと関連しますが、二つ目の質問の場合、 name=a; としているので、結果として *name = a[0] = *a name = &a[0] = a という関係になります。 printf関数の中で %s を指定した場合はそれに対応する引数として、char型の ポインタを指定してやる必要があります。つまり、 printf("%s\n", name); で正しい動作となります。ただし、ご質問の使い方であれば name も余分で、 gets(a); printf("%s\n", a); とすれば十分だと思います。 printf("%s\n", *name); としてしまった場合は a[0] をアドレスとしてprintf関数に渡してしまったこ とになり、255以下のアドレスを利用しようとします。 通常このアドレスは特殊な領域を指すことが多く、Windowsなどのメモリ管理 のきちんとした環境では実行したときにエラーが出ます。 >上記の整数では*はつけたままでもエラーしません。 これについてはint型の a[0] にたまたま有効な数値が入っていたなどの理由 が考えられます。 長文になってしまいました。 引数の拡張仕様の知識が古いので正確かどうかわかりませんが、以上のような 説明でスッキリしましたでしょうか。 ポインタはだれしも苦労するところです。がんばっていろんなプログラムを作 ってください。

yuki22
質問者

お礼

ポインタは誰しも苦労するところです・・、よかったです。私だけいくら理解しようとしても解らないのでぜんぜん才能の欠片もないのでは・・って思ってました。 今度はもう少し大きなプログラムでポインタを入れて活用してみようとおもいます。 丁寧なご指導ありがとうございました。

回答No.3

使い方については場合によるのでなんともいえませんが(その例だと変数は一つでいいんじゃないかとか、iを使わずにpをインクリメントしたらどうかとか)、10個整数を入力して平均を出すとかそういう場合には使うかもしれません。(scanfが悪であるとかいう話はさておいて)お好みでかまわないのではないでしょうか。 下は(getsはどうなのかという論争は避けますが)、*をつけない場合にprintfに渡されるのはポインタであるのに対して、*をつけた場合に渡されるのはポインタの指し示す値(aの一番目に格納された値)になるのですが、%sの場合欲しい値の型はポインタということになるわけで、*をつけた場合には型の不一致ということになるという話です。 上のもので*をはずしてみると頓珍漢な値が出てくると思いますのでお試しあれ。

yuki22
質問者

お礼

むむ、お返事いただいた内容に大変興味深い事も書かれてます・・。 お返事ありがとうございます。参考にさせていただきます。

  • harlan
  • ベストアンサー率77% (234/303)
回答No.2

プログラム1 この例では、ポインタや2次元配列を使う積極的な理由はないように思われます。 以下のような書き方では、問題がありますか? #include <stdio.h> int main() { int a[2],i=0; scanf("%d",&a[i]); printf("%d\n",a[i]); i++; scanf("%d",&a[i]); printf("%d\n",a[i]); return 0; } プログラム2 整数型とキャラクタ型の違いではなく、printf()の使い方の問題です。 %dの時は値渡しですが、%sで文字列を表示する時は、アドレス渡しにしなければいけませんので printf("%s\n",name); と、しなければいけません。

yuki22
質問者

お礼

そうでしたか~。 経験豊富な方々ってどの様な時にポインタを使用するのかよくわからなくて、こんな使いかたもするの??と思っていたのです。ポインタを使わなくても出来そうな時はシンプルにしたほうがいいのですね。 お返事ありがとうございました。

  • kochory
  • ベストアンサー率45% (167/370)
回答No.1

質問文中の、下のほうのプログラムで、 printfの%sを%cに変えて動作を確かめてみてください。 その後、C言語における「文字列」の扱いについて (「文字型(char型)変数」と「文字列」の違いについて) 教科書やウェブサイトで調べてみてください。

yuki22
質問者

お礼

まだまだ調べ方が足らなかったのですね。 大切なお時間を回答にお使いいただきありがとうございました。

関連するQ&A

  • c言語なのですが

    c言語なのですが #include<stdio.h> main() { int a; printf("整数を5回足し算する\n"); scanf("%d %d",&a); printf("a*5=%d\n",a*5); return(0); } でエラーが起こります どこを修正すればいいのでしょうか

  • C言語の配列について

    配列を20 定義し値を入力して合計値を出したいのですがどうすればよいのでしょうか 下のソースでエラーはおこりませんでした 何がちがうのでしょうか #include <stdio.h> int main() { int a[20]={}; int i, sum; printf("整数を入力してください:"); scanf("%d",&a); printf("\n"); for (i = 0; i < 10; i++) { sum += a[i]; } printf("sum= %d\n", sum); return 0; }

  • C言語の初歩的な質問

    質問1----------------------------------------- #include<stdio.h> int main() {  int a;  char b[10];  for(int i = 0;i < 2;i++){   scanf("%d",&a);   printf("整数%d\n",a);  }  scanf("%s",b);  printf("文字列%s\n",b); } /* この際に、例えばabと入力すると結果が 整数-858993460 整数-858993460 文字列ab となり整数入力を無視して進められるのはなぜでしょうか? */ 質問2----------------------------------------- #include<stdio.h> void func(int**); int main() {  int *p;  func(&p);  printf("%d",*p); } void func(int **pp) {  int n = 10;  *pp = &n; } /* func関数のnはスコープからはずれて変数の寿命がなくなるはずなのにprintfで表示されるのはなぜでしょうか? */ ---------------------------------------------- C言語は一冊の本とネットの入門サイトをかじった程度の理解です。

  • C言語 %表示

    二つの整数値を読み込んで、前者が後者の何%かを表示するプログラムを作成したいです。 #include<stdio.h> int main(void){ int no1,no2; printf("整数を入力してください。\n"); printf("整数A:"); scanf("%d",&no1); printf("整数B:"); scanf("%d",&no2); printf("Aの値はBの値の%f%%です。\n",(double)(no1/no2)); } Aの値はBの値の0.0000%です。となってしまいます。 上記のプログラムの訂正をお願いします。

  • C言語の問題を教えてください。初心者です。

    1000以下の整数を入力して、それ以下の素数を出力するプログラムをつくっています。 一応自分でやってみたのですが、どうもうまくできません。自分ではどこが間違っているのかさっぱりなので間違い箇所を指摘し、どうすれば良いのかを教えていただきたいです。ほかに効率的なやりかたがあったらあわせてお願いします。 初心者なので易しく説明していただけるとありがたいです。 <自分でやってみた> #include <stdio.h> int main(){ int i,j,N; int a[1000]; for (i=2; i<=1000; i++) { a[i]=1; } for (i=2; i<=1000; i++) { for (j=i++; j<=1000; j++) { if (a[j]=1 && j%i==0) { a[j]=0; } } } printf("2以上1000以下の整数を入力してください\n"); scanf("%d",&N); printf("%d以下の素数は\n",N); for (i=2; i<=N; i++) { if (a[i]=1) { printf("%d\n",i); } } } よろしくお願いしますm(_ _)m

  • C言語について

    「条件演算子(a?b:c)を使って、三つの整数値を読み込んで、その最小値を求めて表示するプログラムを作成せよ」という問題を初心者なりに自分で以下のように解いてみたのですが、もっと簡単に表示できるプログラムがあれば教えてください。 #include<stdio.h> int main(void) { int na,nb,nc,min; printf("整数1:"); scanf("%d",&na); printf("整数2:"); scanf("%d",&nb); printf("整数3:"); scanf("%d",&nc); (na<nb)?min=na:min=nb; printf("最小値は%dです。\n",(nc<min)?min=nc:min); return 0; }

  • c言語超初心者です。2

    #include <stdio.h> int main(void) { int na,nb, nc; int sum; double ave; puts("三つの整数を入力してください."); printf("整数A:"); scanf("%d", &na); printf("整数B:"); scanf("%d", &nb); printf("整数C:"); scanf("%d", &nc); sum=na+nb+nc; ave=(double)sum/3; printf("それらの合計は%5dです。\n", sum); printf("それらの平均は%5.1fです。\n",ave); return(0); } とういうのを作ったんですが、最後のそれらの合計は%5dとやりその5の意味は整数を10進法で少なくても5桁で表示とありますが、例えば1,2,3と入力しても合計は6とでて5桁ででないんですけど。そういう意味ではありませんか?あとave=(double)sum/3;のところをave=sum/3.0としても問題なくできるのですが、どっちでやったほうがいいとかはありますか?もしあったらその理由も教えてください。

  • C言語について。初心者です。

    参考書の問題で、「整数値以下である正の偶数を照準に表示するプログラムを作成せよ」 例)整数を入力してください:19   2 4 6 8 10 12 14 16 18 とあり、自分で以下のプログラムを作ってみたのですが「222222・・・・・・・・・・・・・・・・・・」となるだけです。どう変えればちゃんと表示されるようになりますか?ちなみにwhile文を使うのが条件です。 #include<stdio.h> int main(void) {       int na; int nb=0; printf("整数を入力してください。:"); scanf("%d",&na); while(nb<na) printf("%d",nb+2); putchar('\n'); return 0; }

  • c言語超初心者です。教えてください

    基本的だと思いますが教えてください。 #include <stdio.h> int main(void) { int na, nb: puts("二つの整数を入力してください."); printf("整数A:”); scanf("%d",&na); printf("整数B:”); scanf("%d",&nb); printf("それらの平均は%fです。\n,(na+nb)/2.0); return(0); } これでintの形で最後のprintfが%fなのですがintは%dとなるはずなのですがこれは2。0という実数値で割るから答えは実数値になりますよ。という意味で%fとしたのでしょうか?確かにこうしないと正しい値がでてこないのです。教えてください。

  • 教えてください。C言語初心者です。

    #include <stdio.h> int main() { int sentaku,hakoA=0,hakoB,*kiroku[10]; char *name[10]; while (sentaku !=3){ printf("1:新規登録\n"); printf("2:データ確認\n"); printf("3:終了\n"); scanf("%d",&sentaku); switch (sentaku){ case 1: printf("登録する名前を入力してください。---"); scanf("%s",name[hakoA]); printf("記録を入力してください。---"); scanf("%d",&kiroku[hakoA]); printf("登録番号は%d番です。\n",hakoA); hakoA++; printf("登録を終了します。\n"); continue; case 2: if (hakoA==0){ printf("登録されてません\n"); continue; }else{ printf("登録番号を入力して下さい。---"); scanf("%d",&hakoB); printf("%s君で記録は%dです。\n",name[hakoB],kiroku[hakoB]); continue; } case 3: break; default : printf("1~3でお願いします。\n"); continue; } } return 0; } このプログラムはコンパイルされたのですが、実行で入力してるとエラーになってしまうのです。 まだ勉強始めたばかりでちょっとなぜか解らないのです。どこかおかしいところがありましたらご教授いただけると嬉しいです。おねがいします。

専門家に質問してみよう