配列とポインタについて熱く論じてくれ。
■ このスレッドは過去ログ倉庫に格納されています
0001rerorero
NGNGint a[3]のとき、
配列名aは、式の中ではポインタと「みなされる。」
int a[3];
a[0]=10;
a[1]=20;
a[2]=30;
printf("%d\n",*a); 10が表示される
printf("%d\n",*(a+1)); 20が表示される
printf("%d\n",*(a+2)); 30が表示される
*aってのは、ポインタaが指している先の変数を
表す。
ってことから、aはポインタと解釈されていることがわかる。
ただ、aは「ポインタと解釈されている」のであって、
ポインタではない。
というのも、
配列の先頭要素のアドレスは
固定された値、すなわち「定数」であり、
定数にアドレスを代入することはできない。
それに対し、ポインタは「変数」である。
どうでしょね?
0002デフォルトの名無しさん
NGNG0003わかりません
NGNG0004デフォルトの名無しさん
NGNG███▀ █████████ ▄▄▄▄█████▀▀ ████▀▀
███▀ ██ ███▀ ▄███▀ ▀▀▀▀ ███▀
██▀ ▄███▀███▄▄▄███ ▄▄▄█▀
▄███▄▄██▀ █▀ ▀████ ▀██▄
▀▀▀▀███▄ ▄██▀█▄▄ ███
██▀ ███ ██▀ ▀███▄▄ ███
▄████▀▀██ ▄█▀▄▄ ▀█████▄▄ ███
▀█▀▀ █▄▄█▀ ████▄ ▀███▀▀▀ ███
▄ ███ ▀███ ▀▀▀ ███
███ ███ ▀▀ ███
███ ▀ ▀████▄ ▄▄▄▄████
▀ ▀████ ▀█████
▀██▀
0005デフォルトの名無しさん
NGNG███▀ █████████ ▄▄▄▄█████▀▀ ████▀▀
███▀ ██ ███▀ ▄███▀ ▀▀▀▀ ███▀
██▀ ▄███▀███▄▄▄███ ▄▄▄█▀
▄███▄▄██▀ █▀ ▀████ ▀██▄
▀▀▀▀███▄ ▄██▀█▄▄ ███
██▀ ███ ██▀ ▀███▄▄ ███
▄████▀▀██ ▄█▀▄▄ ▀█████▄▄ ███
▀█▀▀ █▄▄█▀ ████▄ ▀███▀▀▀ ███
▄ ███ ▀███ ▀▀▀ ███
███ ███ ▀▀ ███
███ ▀ ▀████▄ ▄▄▄▄████
▀ ▀████ ▀█████
▀██▀
0006デフォルトの名無しさん
NGNG███▀ █████████ ▄▄▄▄█████▀▀ ████▀▀
███▀ ██ ███▀ ▄███▀ ▀▀▀▀ ███▀
██▀ ▄███▀███▄▄▄███ ▄▄▄█▀
▄███▄▄██▀ █▀ ▀████ ▀██▄
▀▀▀▀███▄ ▄██▀█▄▄ ███
██▀ ███ ██▀ ▀███▄▄ ███
▄████▀▀██ ▄█▀▄▄ ▀█████▄▄ ███
▀█▀▀ █▄▄█▀ ████▄ ▀███▀▀▀ ███
▄ ███ ▀███ ▀▀▀ ███
███ ███ ▀▀ ███
███ ▀ ▀████▄ ▄▄▄▄████
▀ ▀████ ▀█████
▀██▀
0007デフォルトの名無しさん
NGNG▄▄▄██████▄
███▀ █████████ ▄▄▄▄█████▀▀ ████▀▀
███▀ ██ ███▀ ▄███▀ ▀▀▀▀ ███▀
██▀ ▄███▀███▄▄▄███ ▄▄▄█▀
▄███▄▄██▀ █▀ ▀████ ▀██▄
▀▀▀▀███▄ ▄██▀█▄▄ ███
██▀ ███ ██▀ ▀███▄▄ ███
▄████▀▀██ ▄█▀▄▄ ▀█████▄▄ ███
▀█▀▀ █▄▄█▀ ████▄ ▀███▀▀▀ ███
▄ ███ ▀███ ▀▀▀ ███
███ ███ ▀▀ ███
███ ▀ ▀████▄ ▄▄▄▄████
▀ ▀████ ▀█████
▀██▀
0008デフォルトの名無しさん
NGNGなんか大迫力
0009デフォルトの名無しさん
NGNG>固定された値、すなわち「定数」であり、
これ、間違ってんじゃない?
0010デフォルトの名無しさん
NGNG0011デフォルトの名無しさん
NGNG>>1 ですか?
0012デフォルトの名無しさん
NGNGポインタ=C言語でアドレスを操作しやすいように作った「変数」
ポインタが表すのは実際のアドレスでない(バイト数等を意識しなくてよい)
ポインタ*aのアドレスaは、その変数が占めるバイト数に係わらず、必ず占有するメモリの先頭を指す
int a[20]; とした場合 20個のint型のメモリのかたまりと、1つのアドレスを入れるメモリの位置が確保される
a[0]は、*aで参照出来る
C言語ではポインタと配列変数は全く同じものとして扱われるため、
int *a;int a[20];
という宣言はエラーとなる。
またC言語には、”配列で宣言したもは、特別な必要が無い限り配列として扱う”という原則がある。
配列セグメントの先頭アドレスになるようなポインタに違う値を代入したら指してる配列があるメモリのかたまりと違う所に行って
オフセットもクソもなくなるし要素のバイト数とかもあるからポインタ変数にムチャクチャなアドレス入れて使うのと同じくらいやらない事なのでは?
0013デフォルトの名無しさん
NGNG0014デフォルトの名無しさん
NGNG0015デフォルトの名無しさん
NGNGそれを読んだから講釈垂れたかったんだろ1は。
0016rerorero
NGNGその本を読んだらおかしくなってきたんよ。
講釈をたれたいんでなく、この本のせいで
またドキュソになっちまった自分と舞えはしに
むかついてんだよ。
舞え端は、はっきりいって異端者だ。
ところで、
>int *a;int a[20];
>という宣言はエラーとなる
ってのはわかる。
だが、
aは、先頭要素のアドレス&a[0]をもっている。
つまり、a[0]を指してるんだよな。
やっぱポインタとして解釈されてる
とおもっていいのでは?
そうでないなら、なんでエラーにはならんのだ?
0017rerorero
NGNGa[0]は、*(a+0)の簡便記法らしい。
まあ、それはよいとして、
「aはa[0]を指している」
ってのは許されんのか?
この考え方でつきすすんでいって障害は別に
なかった。
0018デフォルトの名無しさん
NGNG0019前橋信者
NGNG0020デフォルトの名無しさん
NGNGhttp://member.nifty.ne.jp/maebashi/seiha/hosoku001.html
0021デフォルトの名無しさん
NGNG>int a[20]; とした場合 20個のint型のメモリのかたまりと、1つのアドレスを入れるメモリの位置が確保される
これは配列と配列を指す事実上のポインタがあるってことだと思うが
規格は知らんものの実際にそんな実装になっちゃいないと思う。
それと、ポインタと配列の違いとして sizeof の適用結果の違いも忘れるべからず。
0022rerorero
NGNGは承知
何度もわるいな。
舞えはしがいうには、
配列をあたかもポインタのようにしてつかうことができる。
int d[]={
1111,2222,3333
};
このとき、
配列の第1要素の値 *d
配列の第2要素の値 *(d+1)
配列の第3要素の値 *(d+2)
とはかいているものの、
配列名dは、先頭要素をさすポインタ
である。
とはかいていないのだ。
これにむかついてんだよ、おれは。
さんざん、K&Rを批判しておきながら、
曖昧にしてる点がおおいんだよ。
あっちこちはなしとんでるしよ。
0023デフォルトの名無しさん
NGNG>配列名dは、先頭要素をさすポインタである。
これは、式中において配列変数はポインタとして評価される、とだけ言うべきだろう。
あくまでもポインタと見なすだけであって配列とポインタは別々のもの。
これは >>1 で自分が書いたとおりの話。
それを前橋式には「配列(変数)を(式中においては)あたかもポインタのようにしてつかうことができる」と書いてるだけじゃないの?
目くじら立てるようなもんじゃないと思うがなぁ。
0024デフォルトの名無しさん
NGNG>規格は知らんものの実際にそんな実装になっちゃいないと思う。
できれば理由書いて欲しかったんですが
0025デフォルトの名無しさん
NGNG0026rerorero
NGNGvoid sub(int **,int);
int main(void)
{
int *p[3];
int a=10;
int b=11;
int c=12;
p[0]=&a;
p[1]=&b;
p[2]=&c;
sub(p,3);
return 0;
}
void sub(int **x,int n)
{
int i;
for(i=0;i<n;i++){
printf("%d\n",*x[i]);
}
}
int *a[]と int **a
は同じだってやつだけど、
pはp[0]をさすポインタとみなされる。
p[0]はint型をさすポインタである。
つまり、
pは、"int型をさすポインタ"へのポインタである。
ゆえに、受け取り側の仮引数は
int **a
とすればよい。
このような考え方はいいのだろうか。
0027デフォルトの名無しさん
NGNGつまりdはintの配列(データ領域)を指すポインタ値を保持するものであって、
d自体だけで言えば、int const *dとして考えても差し支えないのではないか、ってことか?
文章の解釈間違ってたらスマソ。
0028デフォルトの名無しさん
NGNG3214 + 22;
3214 + 41324;
などのなかでは3214はintであるかのようにふるまう。しかし3214はintではない。これは
3214 = 1;
がエラーになることからもわかるだろう。
つまり int a[3]のときの配列名aは「ポインタ値」だが「ポインタ変数」ではない。
どうでしょうね?
0029rerorero
NGNG>23
親切にありがとな。
>配列名dは、先頭要素をさすポインタ
>である
悪い。まちがえた。
式の中で、配列名dは先頭要素を指すポインタと解釈される。
ドキュソなおれも、
配列とポインタは全く違うものってのはわかる。
>1で自分で説明してるくらいだから大丈夫だ(藁
ただ、
「式の中で、配列名dは先頭要素を指すポインタと解釈される。」
っていう考えはゆるされるんだよな。
前橋がいうには
>[ ]ってのは単なる演算子だ。
うむ。配列要素にアクセス(参照)する際に用いるんだな。
でも、* は演算子とはいってないだろ?
これはあくまで、ポインタが指す先の変数を表す。
ってことは、*aのaはまぎれもなくポインタではないのか?
なんかおれみおとしたか?
*も演算子か?
んなわけないよな。
0030rerorero
NGNGおれがドキュソはみとめる。
わるいね。
おれがたしかめたいのは、
配列名は、先頭要素を「指している」
のか?
ということなんだ。
0031デフォルトの名無しさん
NGNG……>>1 でほぼ正解じゃん ……
0032デフォルトの名無しさん
NGNG0033デフォルトの名無しさん
NGNG0034デフォルトの名無しさん
NGNG理屈はあとからついてくる。
0035デフォルトの名無しさん
NGNGただ、式中では等価と見なされる場合が多いだけ。
両者は本質的に異なる。
0036デフォルトの名無しさん
NGNGaはdouble型を指す為のポインタ型変数である(double型変数が持つ複数バイト中の先頭バイトのアドレス)
宣言時、「*」は「ポインタ変数型」という意味である。型によって違うバイト数を認識する為 *a; ではなく 型 *a; と表す必要がある。
代入時は a=&b; としたとき *a の参照と b の参照は同じになる( *(&b) )
「*」は右の値(ポインタ)が表す変数への参照演算子のようなもの
arr(*a+1)としたとき、ポインタが指すアドレスは+1されるわけではなく、バイト数に応じた数が加えられる
0037デフォルトの名無しさん
NGNG「《Tの配列》型の式はその配列の最初の要素へのポインタに(暗黙のうちに)変換できる。」
だから、配列名自体はポインタではない。
0038デフォルトの名無しさん
NGNGコンパイラさんは、式の中で配列がポインタだと思って
解釈しようとするだけでしょ。
概念が異なっていても、内部的に同じような状態になることは多いと思う。
003936
NGNG0040rerorero
NGNG>「*」は右の値(ポインタ)が表す変数への参照演算子のようなもの
演算子はいいとして、
やっぱ、"右の値(ポインタ)"・・・ポインタだろ?
な?
配列名はポインタしてるんだよ。やっぱ。
「指している」
んだよな。
何度もいうが、俺は、
「配列名 = ポインタ」
とはおもってない。それは1でのべた。
そしてなんどもいうが、
配列名は、先頭要素を「指している」
のか?
Yes か No で
こたえてくれ。
そしてその理由とな。
>37
親切にありがとな。
でも、それは、前橋の本で理解できてるんだ。
ただ、あの本には、小さな穴がある。
それが
配列名は、先頭要素を「指している」
のか?
なんだ。
*をつかえば、各配列要素にアクセスできることはわかる。
*aをオフセット(基準にして)、型サイズ*nでインクリメント
できる
ってのもわかる。
0041デフォルトの名無しさん
NGNG0042rerorero
NGNG悪い。みおとしてた。
>「《Tの配列》型の式はその配列の最初の要素へのポインタに(暗黙のうちに)変換できる
そうだよな?!
これを確認したかったんだ。
おれは
配列名は、式の中でポインタと「みなされる」
と何度も書いてる。これは理解できるんだ。
確認したかったのは、じゃ、配列名はどこを指してるんだ?
といったら、先頭要素だろ?
ありがとう。
でも、これは憶測だろうか?
確証がとれたものなのだろうか?
K&Rが、こういうことをしっかりと論じてくれないから
ドキュソがさらにドキュソになるんだよな。
0043デフォルトの名無しさん
NGNGドラゴンボールを7つ集めると
配列からポインタが出てくんだよ。
0044UNKOMAN
NGNGprintf("%d\n",*(1[a])); 20が表示される
printf("%d\n",*(2[a])); 30が表示される
a[x] は *(a+x) として解釈されるため。
0045デフォルトの名無しさん
NGNGint *a;
int **b;
int *c[10];
int (*d)[10];
int (*e)(int f);
これぐらいが分かればいいんじゃない?ポインタは。
0046デフォルトの名無しさん
NGNG> のか?
> Yes か No で
> こたえてくれ。
No
配列は「存在している」だけ
0047デフォルトの名無しさん
NGNG>といったら、先頭要素だろ?
配列名が指すものは「配列」だよ。sizeofを考えてみたら?
0048デフォルトの名無しさん
NGNGアドレス ポインタ 配列(3byte) 参照
__________
0x1001 = a ←|__ __|
0x1002 |_ a[0] __| > *a
0x1003 |_________|
参照 a[0] は *a と等価
配列名 a は a[0] を指すポインタと等価にみなされるってことか
0049デフォルトの名無しさん
NGNGprintf("%d\n",0[a]); 10が表示される
printf("%d\n",1[a]); 20が表示される
printf("%d\n",2[a]); 30が表示される
な。
0050デフォルトの名無しさん
NGNG0051rerorero
NGNGじゃ、
これためしてみな。
#include <stdio.h>
int main(void)
{
int p[3]={1,2,3};
printf("%p\n",p);
printf("%p\n",&p[0]);
return 0;
}
0xbffffab0
0xbffffab0
おなじアドレスだ。
つまり、配列名は先頭要素のアドレスもってるんだ。
ってことは、配列名は、”あたかもポインタのように”
先頭要素を指してるんだ。
>47
配列名が指すものは「配列」だよ
それは
(*a)[3]ってなやつだろ?
このとき、aは、
要素数3の配列をさすポインタだ。
このばあい、aは確かに配列全体をさすよ。
0052rerorero
NGNGアドレス ポインタ 配列(3byte) 参照
__________
0x1001 = a ←|__ __|
0x1002 |_ a[0] __| > *a
0x1003 |_________|
参照 a[0] は *a と等価
配列名 a は a[0] を指すポインタと等価にみなされるってことか
うむ。
メモリ
|
a +----------
a----->| a[0] | *a
a+1 +----------
| a[1] | *(a+1)
a+2 +----------
| a[2] | *(a+2)
----------
だろ?
aが配列全体をさすっていうやつは、
*aで表示されるのはなんなのかこたえてくれ?
0053デフォルトの名無しさん
NGNG0054デフォルトの名無しさん
NGNG漏れ?ワセリン塗って待ってる。
0055rerorero
NGNGa +----------
a----->| a[0] | *a
a+1 +----------
| a[1] | *(a+1)
a+2 +----------
| a[2] | *(a+2)
みずらい(藁
0057rerorero
NGNGTABもだめか?
|
a +----------
a----->| a[0] | *a
a+1 +----------
| a[1] | *(a+1)
a+2 +----------
| a[2] | *(a+2)
----------
0058rerorero
NGNGアスキーアートつぶしか?(藁
005948
NGNG0060デフォルトの名無しさん
NGNGWhat you see is not always what you get.
0061デフォルトの名無しさん
NGNGお前、頭悪いな。用語は、ちゃんと使え。
> おなじアドレスだ。
> つまり、配列名は先頭要素のアドレスもってるんだ。
> ってことは、配列名は、”あたかもポインタのように”
> 先頭要素を指してるんだ。
と、「配列名」とか言っておきながら...
> 配列名が指すものは「配列」だよ
> それは、
> (*a)[3]ってなやつだろ?
> このとき、aは、
> 要素数3の配列をさすポインタだ。
とか言ってるけど、この「a」ってなんだよ。誰が、配列を指すポインタなんか議
論してんだ ?
ちなみに、>>47 の言う「sizeofを考えてみたら?」って言うのは、理解してん
のか ?
0062WYSIWYG!!
NGNGint main(void)
{
int p[3]={1,2,3};
printf("%p\n",p);
printf("%p\n",&p[0]);
printf("%p\n",&*(&p[0]));
printf("%p\n",&(&p[0])[0]);
return 0;
}
全て同じっと。
0063デフォルトの名無しさん
NGNG>aが配列全体をさすっていうやつは、
>*aで表示されるのはなんなのかこたえてくれ?
*aの値としてはa[0]だろ。単項演算子*はオペランドにポインタを必要とするから、
配列名からポインタに暗黙に変換されるんだよ。
明示的に書くと *(&a[0]) ってなる。
0064デフォルトの名無しさん
NGNG右辺値でも型情報があれば参照できる。
*(char*)0x000000
とかな。
0065デフォルトの名無しさん
NGNG■ このスレッドは過去ログ倉庫に格納されています