dポイントプレゼントキャンペーン実施中!

ポインタを宣言するとメモリ上に、ポインタ変数を格納するための領域が確保されます。ポインタ=アドレスというのは大丈夫なのですが、

int *b

のようにどうして、ポインタに型があるのでしょうか?単に変数のアドレスを表示するだけならば型はいらないと思うのですが。

またこのとき宣言された変数は *b ではなくて b であってますよね?

A 回答 (12件中1~10件)

>初心者の自分にはハードルの高い内容ですね。


ハードルが高いとは思いませんが、むしろ初心者だからこそ、
そういった決まりを知っておく必要があると私は思います。

>>sizeof(char *)とsizeof(int *)とが同じであることと、
>>sizeof(char)とsizeof(int)とが異なることとを
これをしようとしているのでしょうが、
No7さんの意図した所としては、
>>char a, *b;
>>int c, *d;
>>printf("%d",sizeof(a));
>>printf("%d",sizeof(b));
>>printf("%d",sizeof(c));
>>printf("%d",sizeof(d));
ということですよ?
>>sizeof(char *型)とsizeof(int *型)とが同じであることと、
>>sizeof(char型)とsizeof(int型)とが異なることとを
と読み替えるべきです。

>>どうして、ポインタに型があるのでしょうか?
>まず大前提はこの質問です。
No2でも触れましたが、C言語では
型はその型分類によって特徴付けられ、
型によって表現範囲が異なり、
何byteでそれを表すかが処理系によって定義されます。

処理系は通常これを「型情報」として管理する為、
ポインタにも参照する為の、内訳をするための、
一種の方法として、型が存在しているものと思われます。

> これはデータが複数の番地にまたがって存在しているし、
> charとintでそれぞれサイズがことなるからですよね?
そうです。
その内容を取り出すためには、
ポインタを参照する際に表現するのに使う、
実際のサイズが分からないと、
アドレスから値を取り出す場合に、
アドレス上から何バイトを取り出せば良いか
分からないということが一概にあります。

蛇足ですが。。。
例えば 1byte = 8bit の処理系で,
32ビット環境の番地に入っているビットを見ると。。。
aの番地を 10000 、paの番地を30000 とすると、
char a = 1;
10000 : 0000 0001
char *pa = &a
30000 : 0001 0000
30001 : 0010 0111
30002 : 0000 0000
30003 : 0000 0000

a = 10;
10000 : 0000 1010
*pa = 255;
30000 - 30003

0000 0000 0000 0000 0010 0111 0001 0000 (BE)

10000 から型情報により 1byte

10000 : 1111 1111

bの番地を 20000 , pbの番地を40000 とすると、
int b = 1;
20000 : 0000 0001
20001 : 0000 0000
20002 : 0000 0000
20003 : 0000 0000
int *pb = &b;
40000 : 0010 0000
40001 : 0100 1110
40002 : 0000 0000
40003 : 0000 0000

b = 256;
20000 : 0000 0000
20001 : 0000 0001
20002 : 0000 0000
20003 : 0000 0000
*pb = 65535;
40000 - 40003

0000 0000 0000 0000 0100 1110 0010 0000(BE)

20000 から型情報により 4byte

20000 : 1111 1111
20001 : 1111 1111
20002 : 0000 0000
20003 : 0000 0000

ってイメージでしょうか。
#あくまでも処理系によっては異なるのですが。。。

型情報で多くあるミスは、配列型のサイズです。
文字列などの配列をC言語上で言うと
char型配列などになりますが、
関数などにこれを渡すときに暗黙の変換が行われ、
型情報が失われsizeofを使用しても渡した元の配列の
サイズを取得することができなくなります。

#include <stdio.h>
int sub( char [] );
int main( void )
{
 char str[] = "hogehoge";
 printf( "%d\n", sizeof(str)); // strの型情報は char[9]
 sub( str ); // 暗黙の変換により型情報が失われて渡される
 return 0;
}
int sub( char str[] )
{
 printf( "%d\n", sizeof(str)); // strの型情報は ポインタ
 printf( "%d\n", sizeof(*str)); // *strの型情報は char になる
}
    • good
    • 0
この回答へのお礼

丁寧な回答ありがとうございます。皆様の指摘でだいぶ理解が深まりました。

お礼日時:2008/11/29 08:32

>printf("%d",sizeof(a));


>printf("%d",sizeof(*b));
>printf("%d",sizeof(c));
>printf("%d",sizeof(*d));
>でためしたらそれぞれ4411でintとcharのサイズが同じになりました。どこが間違えでしょうか?

1番目のsizeofはint型のサイズを、
2番目のsizeofはint型へのポインタが「指し示す先」(=int型)のサイズを、
3番目のsizeofはchar型のサイズを、
4番目のsizeofはchar型へのポインタが「指し示す先」(=char型)のサイズを
それぞれ返しています。
ポインタ変数を使用するときに変数名の前に*を付けると、指し示す先の内容ということになります。
ポインタ変数自体のサイズが欲しい場合は、*は付けません。
    • good
    • 0
この回答へのお礼

回答ありがとうございます。知りませんでした。

お礼日時:2008/11/29 08:29

>どうして、ポインタに型があるのでしょうか?


>単に変数のアドレスを表示するだけならば型はいらないと思うのですが。

ポインタが指すアドレスからデータを出したり、データを入れたりする場合や、ポインタを動かす場合に、データサイズが判らないと困ります。

例えば、ポインタが1254番地を指している場合「ポインタが指す1254番地からデータを取り出して」と言われた場合、そこにあるデータが「charのデータ」なのか「intのデータ」なのか判らないと、取り出せません。

また、ポインタが1254番地を指している時「1つ進めて」と、ポインタに1を足した場合、アドレスを幾つ進めれば良いか判りません。

なので「ポインタにも型が必要」なのです。
    • good
    • 0
この回答へのお礼

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

「ポインタが指す1254番地からデータを取り出して」と言われた場合、そこにあるデータが「charのデータ」なのか「intのデータ」なのか判らないと、取り出せません。

(初歩的なことですが)これはデータが複数の番地にまたがって存在しているし、charとintでそれぞれサイズがことなるからですよね?

お礼日時:2008/11/29 01:08

>No6さん


私のコンパイラではワーニングになりました。
例えが悪かったみたいですね、その点はすみませんでした。
しかし質問への回答として、本質的な部分で間違えているとは思いません。
勿論実行する上で支障はないでしょうが、型について語る時に3.14(float)と3(int型)が同じ扱いで良いわけがありません。

>No.7さん
>どうして、ポインタに型があるのでしょうか?
まず大前提はこの質問です。
>ではdoubleやcharの型の場合だとintと何が異なるのでしょうか?
>メモリ上で確保する領域のサイズは同じはずですよね?
だとすれば、doubleやcharは暗黙的にcouble*やchar*と解釈できると思うのですが。
No.7さんが仰るとおり、double*もchar*もint*も確保するサイズは同じはずです。
    • good
    • 0
この回答へのお礼

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

double*もchar*もint*も確保するサイズは同じはずです

とのことですが、よく考えたらそうですよね。
しかし

#include <stdio.h>
#include <stdlib.h>

/*
*
*/
int main(int argc, char** argv) {

int a;
int *b;
char c;
char *d;

printf("%d",sizeof(a));
printf("%d",sizeof(*b));
printf("%d",sizeof(c));
printf("%d",sizeof(*d));

return (EXIT_SUCCESS);
}

でためしたらそれぞれ4411でintとcharのサイズが同じになりました。どこが間違えでしょうか?

お礼日時:2008/11/29 01:05

>#4さん


>私流に言うと「int a = 3.14;」これがエラーになるのと同じ理由です。

そもそも、これがエラーを起こすというのが間違いの始まりですね。
コンパイルすると警告は出るかもしれませんが、
int型の変数aに3という値を「正しく」格納します。
    • good
    • 0
この回答へのお礼

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

お礼日時:2008/11/29 00:41

>メモリ上で確保する領域のサイズは同じはずですよね?



sizeof(char *)とsizeof(int *)とが同じであることと、
sizeof(char)とsizeof(int)とが異なることとを
混同なさっていませんか?
    • good
    • 0
この回答へのお礼

回答ありがとうございました。
僕の環境ではsizeof(char *)とsizeof(int *)は違いました。それぞれ4、1でした。

お礼日時:2008/11/29 00:40

>#4さん


>*p = 3.14; //a=3.14;これはエラーにしないとまずいですよね? だから整数を示すためにint*が必要。

なぜエラーにしないとまずいのですか?
pが指すint型の領域に、3.14の小数点以下を切り捨てた3が正しく入りますよ。
何か勘違いされてませんか?
    • good
    • 0
この回答へのお礼

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

お礼日時:2008/11/29 00:35

> メモリ上で確保する領域のサイズは同じはず



えーと……

sizeof(char)
sizeof(int)
sizeof(double)

さてそれぞれいくつになるでしょうか。
問題なのは「アドレスのサイズ」じゃなくて「アドレスが指す先にあるもののサイズ」なのです。
    • good
    • 0
この回答へのお礼

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

お礼日時:2008/11/29 00:34

この疑問は核心をついたというか、考え方は間違ってないと思います。


むしろ私も、文字はchar、整数はint、だったらアドレスはint*とかじゃなくてpoint型だろうと思うんですよね。
ちなみに漠然とアドレスを渡したい場合が実際ありまして、そういう場合は「void*」という宣言を使います。

型が必要な理由は、もう既に十分な回答が出ているようですね。
私流に言うと「int a = 3.14;」これがエラーになるのと同じ理由です。
int a=0;
int* p = &a;
*p = 100; //a=100;
*p = 3.14; //a=3.14;これはエラーにしないとまずいですよね? だから整数を示すためにint*が必要。
    • good
    • 0
この回答へのお礼

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

お礼日時:2008/11/29 00:33

こんばんは.



ポインタに型がある理由の一つは「ポインタ演算」のためです.
int num[2], *pnum;
なる宣言があるとして,
pnum = num;
とすれば *pnum はnumの先頭の値を参照します.
次に
pnum++;
とすると *pnum はnumの2番目の値を参照します.
ごく普通にやっていることですが,上記のことを行うには
pnum = pnum + 1
という演算が「pnumをint型のサイズだけ移動する」ことでなければなりません.
単純に pnum がアドレスの値だけを格納していて,それを1加算する意味しか持たないなら,
pnum++ はint型(大体は32bit)の変数の「途中」を指してしまいます.

要するにポインタに型があることで「加減算のときの飛び幅」を自動的に調整できます.
実際,
double *pdnum;
に関して, pdnum++; としたときと pnum++;としたとき,
それぞれがdouble型要素一つ分,int型要素一つ分ジャンプしてくれることでしょう.
ですが,型がなければ上記の演算は
pdnum += sizeof(double)
pnum += sizeof(int)
と書かねばならないということです.
    • good
    • 0
この回答へのお礼

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

お礼日時:2008/11/29 00:32

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!