※ ChatGPTを利用し、要約された質問です(原文:C言語、配列とポインタとアスタリスクの関係)
C言語の配列とポインタの関係について疑問があります
このQ&Aのポイント
C言語の配列とポインタの関係について疑問があります。配列の宣言とポインタの宣言はどう違うのか、アスタリスクの意味とは何か、printfでの表示方法について知りたいです。
C言語の配列とポインタについて疑問があります。特に、配列とポインタ変数の宣言の違いや、アスタリスクの役割について詳しく教えていただきたいです。
C言語の配列とポインタに関して疑問があります。特に、配列の宣言方法とポインタの宣言方法の違いや、printfでのアドレスと値の表示方法についてわかりやすく説明していただけると嬉しいです。
ちょっと行き詰まっています。
苦しんで覚えるCで勉強しているのですが、まさに苦しんでいます。
http://9cguide.appspot.com/19-01.html
#include <stdio.h>
#include <stdlib.h>
int main()
{
int i;
int *heap;
heap = (int *)malloc(sizeof(int) * 10);
if (heap == NULL) exit(0);
for (i = 0;i < 10;i++) {
heap[i] = i;
}
printf("%d\n",heap[5]);
free(heap);
return 0;
}
int *heap;
ここで int ポインタを宣言しています。
heap = (int *)malloc(sizeof(int) * 10);
ここでヒープを確保しています。(int *) のキャストも sizeof(int) も理解できました。
for (i = 0;i < 10;i++) {
heap[i] = i;
}
まず1点目の疑問はここです。
変数 heap は「ポインタ変数」です。それでいて配列です。
ポインタ変数は、プログラムの文中で通常の変数として使うときには「*heap」のように先頭にアスタリスクを付けなければならかなったと記憶しています。
アスタリスクなしの「heap」はアドレス格納用の変数ではないでしょうか。
printf("%d\n",heap[5]);
そして、その疑問をよそに、この命令が成り立っているようです。
画面上に出される結果は「5」であり、変数「heap」がただの配列として機能しているように見えます。
この printf 次のように書き換えると、エラーが出てコンパイルできませんでした。
書き換え実験1
printf("%p\n",*heap[5]);
アスタリスクを付けて、通常の変数として扱い、受ける方も「%d」から「%p」に書き換えてアドレスを表示してみようと思ったのですが、
「「pointer」を付け忘れています。」というエラーが表示されました。
書き換え実験2
printf("%p\n",heap[5]);
受ける方を「%d」からポインタを受ける「%p」にしましたが、変数の方はアスタリスクなしです。
すると、結果はアドレス「00000005」が返ってきました。
(変数にアスタがないのになぜ?)
書き換え実験3
printf("%d\n",*heap[5]);
これはもうめちゃくちゃですが、一応やってみました。コンパイルエラーで、
「「pointer」を付け忘れています。」というエラーが表示されました。
つまり、こういうことです。
0:printf("%d\n",heap[5]); //5
1:printf("%p\n",*heap[5]); //エラー
2:printf("%p\n",heap[5]); //00000005
3:printf("%d\n",*heap[5]);//エラー
この結果から推測するに、アスタリスクはそもそも付けるとエラーになり、アドレスを表すか、そのアドレスに格納された値を表すかを切り替えるには、単にその変数を受ける「%d」や「%p」を変えるだけ、ということになるのだと思います。
mallocで返ってくるのは、ポインタ変数(の配列)だと思うので、変数のモードを切り替えるためにアスタリスクが必要なのだと思っていましたが、どこかで重大な勘違いをしているようです。
この件について、どなたか教えていただけないでしょうか。
お礼
ありがとうございます。 お礼が遅れましたが、回答はすぐに見ておりました。 試しに、次のように書いてみました。 int array[3] = {5,6,7}; printf("%d\n",*(array +1)); printf("%d\n",array[1]); すると、結果は同じ「6」になりました! 配列の変数は、単体では最初の配列のアドレスで、[]の添字でそれをずらしていたんですね。 そうなってくると、別の回答でも指摘された「ポインタ変数の配列」という解釈そのものがそもそもおかしいと言うことがわかりました。 > *(heap[5]) > となります。 > heap[5] = *(heap+5) より、int型となり、ポインタの演算*が使えないことがわかります。 この部分、納得しました! レベルに合わせて順序立てて説明してくださりありがとうございました!