No.12ベストアンサー
- 回答日時:
>初心者の自分にはハードルの高い内容ですね。
ハードルが高いとは思いませんが、むしろ初心者だからこそ、
そういった決まりを知っておく必要があると私は思います。
>>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 になる
}
No.11
- 回答日時:
>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型)のサイズを
それぞれ返しています。
ポインタ変数を使用するときに変数名の前に*を付けると、指し示す先の内容ということになります。
ポインタ変数自体のサイズが欲しい場合は、*は付けません。
No.10
- 回答日時:
>どうして、ポインタに型があるのでしょうか?
>単に変数のアドレスを表示するだけならば型はいらないと思うのですが。
ポインタが指すアドレスからデータを出したり、データを入れたりする場合や、ポインタを動かす場合に、データサイズが判らないと困ります。
例えば、ポインタが1254番地を指している場合「ポインタが指す1254番地からデータを取り出して」と言われた場合、そこにあるデータが「charのデータ」なのか「intのデータ」なのか判らないと、取り出せません。
また、ポインタが1254番地を指している時「1つ進めて」と、ポインタに1を足した場合、アドレスを幾つ進めれば良いか判りません。
なので「ポインタにも型が必要」なのです。
回答ありがとうございます。
「ポインタが指す1254番地からデータを取り出して」と言われた場合、そこにあるデータが「charのデータ」なのか「intのデータ」なのか判らないと、取り出せません。
(初歩的なことですが)これはデータが複数の番地にまたがって存在しているし、charとintでそれぞれサイズがことなるからですよね?
No.9
- 回答日時:
>No6さん
私のコンパイラではワーニングになりました。
例えが悪かったみたいですね、その点はすみませんでした。
しかし質問への回答として、本質的な部分で間違えているとは思いません。
勿論実行する上で支障はないでしょうが、型について語る時に3.14(float)と3(int型)が同じ扱いで良いわけがありません。
>No.7さん
>どうして、ポインタに型があるのでしょうか?
まず大前提はこの質問です。
>ではdoubleやcharの型の場合だとintと何が異なるのでしょうか?
>メモリ上で確保する領域のサイズは同じはずですよね?
だとすれば、doubleやcharは暗黙的にcouble*やchar*と解釈できると思うのですが。
No.7さんが仰るとおり、double*もchar*もint*も確保するサイズは同じはずです。
回答ありがとうございます。
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のサイズが同じになりました。どこが間違えでしょうか?
No.8
- 回答日時:
>#4さん
>私流に言うと「int a = 3.14;」これがエラーになるのと同じ理由です。
そもそも、これがエラーを起こすというのが間違いの始まりですね。
コンパイルすると警告は出るかもしれませんが、
int型の変数aに3という値を「正しく」格納します。
No.4
- 回答日時:
この疑問は核心をついたというか、考え方は間違ってないと思います。
むしろ私も、文字は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*が必要。
No.3
- 回答日時:
こんばんは.
ポインタに型がある理由の一つは「ポインタ演算」のためです.
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)
と書かねばならないということです.
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
似たような質問が見つかりました
- C言語・C++・C# ポインタの型変換、どうやるんでしたっけ? 2 2022/03/28 11:00
- C言語・C++・C# 関数ポインタの高速化のメリット 7 2023/05/05 20:15
- C言語・C++・C# c言語 コマンドライン引数 4 2023/02/09 18:47
- C言語・C++・C# C言語 ポインタ 配列 2 2022/06/02 17:29
- C言語・C++・C# C言語初心者 ポインタについて、お助けください、、 2 2023/03/15 23:50
- C言語・C++・C# c言語 配列とポインタについて 3 2023/02/09 22:53
- C言語・C++・C# 10個の実数に対する降順ソート結果を出力するプログラムを作りたいのですが、写真のプログラムをどう直せ 2 2022/07/09 21:13
- C言語・C++・C# C言語 配列とポインタについて 2 2022/06/02 11:53
- C言語・C++・C# 10個の実数に対する降順ソート結果を出力するプログラムを作りたいのですが、以下のプログラムをどう直せ 1 2022/07/09 22:16
- C言語・C++・C# C言語: ポインタ 5 2022/06/01 08:33
関連するカテゴリからQ&Aを探す
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
セグメントエラー
-
Run-Time Check Failure #3とい...
-
fopne で失敗する原因
-
ハンドルはポインタか
-
init関数の意味
-
ExcelVBAでのkernel32(64bit)
-
C言語のポインタに直接アドレス...
-
基本アルゴリズムの『返す』の...
-
c言語で任意のファイルから読み...
-
C言語で構造体の参照渡しができ...
-
printfとscanfの違いって・・・
-
どうしてエラーになるかわかり...
-
C言語のポインタとスタックポイ...
-
C言語次のステップ
-
配列とポインタでの書き直しその2
-
関数ポインタの利点
-
ポインタへの代入
-
DLL<->VB間での受け渡し(文字...
-
式の意味が理解できません
-
別のDLLのダイアログを・・・
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
セグメントエラー
-
init関数の意味
-
C言語のポインタに直接アドレス...
-
fopne で失敗する原因
-
Run-Time Check Failure #3とい...
-
C言語の関数と配列に関する質問
-
LPSTR型の初期化について
-
戻り値で構造体を返すことは可...
-
参照型で受け取った引数をポイ...
-
構造体とfscanf
-
ExcelVBAでのkernel32(64bit)
-
アプリを32bitから64bit移行
-
Cで作成したDLL関数をVBから呼...
-
C言語でのconstを返す関数
-
main(int argc,char **argv[])...
-
DLL<->VB間での受け渡し(文字...
-
PASCALとFARの意味
-
エラーの意味
-
ハンドルはポインタか
-
TCHAR文字列内の検索について
おすすめ情報