![](http://oshiete.xgoo.jp/images/v2/pc/qa/question_title.png?5a7ff87)
void foo()
{
int *ptrInt=0;
char *ptrChar=0;
ptrInt++;
ptrChar++;
}
Windows2000上で、上記を実行すると
ptrIntは4になります。
ptrCharは1になります。
なぜでしょうか。
32ビットとはいえ、
ptrIntとptrCharはアドレスを示しますよね。
アドレスに1加算するのだから、
int型、char型に関係なく、
いずれも1になるべきだと思います。
int型のポインタの場合示すデータは4バイトなので、
ポインタ1加算は、4(バイト)加算になるということでしょうか。
No.5ベストアンサー
- 回答日時:
mtsed さんは「ポインタ」とは「アドレス」であると思っているようですね。
まず、ポインタは「型」であると覚えたほうが良いと思います。
そして、ただの「ポインタ型」というものがあるわけではなく、必ず「何かの型へのポインタ型」になるわけです。
ですので、「char型へのポインタ型」と「int型へのポインタ型」とは別の型になるわけです。
そして、ポインタ演算をすると、この「○○型へのポインタ型」の○○型のサイズ分だけアドレスが加算されるわけです。
ちなみに、一般に単に「○○型へのポインタ」と言った場合、次の3つのいずれかの意味で使われていると思います。
1. ○○型へのポインタ型
2. ○○型へのポインタ型の変数
3. ○○型へのポインタ型の値
私は意識して使い分けるべきだと思うのですが、私の周りをみると結構いい加減な人が多いのも事実のように思います。
たとえば、以下の例の場合を考えて見ます。
----------------------------------------
int *hoge_ptr;
int hoge;
hoge_ptr = &hoge;
----------------------------------------
この場合、
「int *」が「int型へのポインタ型」をあらわしています。
「hoge_ptr」は「int型へのポインタ型の変数」として定義されます。
そして、hoge は「int型の変数」なので、&hoge は「int型へのポインタ型の値」を持つことになります。
hoge_ptr は「int型へのポインタ型の変数」ですから、当然「int型へのポインタ型の値」しか設定することができません。
そうしないと、*hoge_ptr としたときに正しい値を読み出せないですよね?
このあたりの話は問題ないと思いますが…大丈夫ですよね?
# 大丈夫な場合は、大変失礼いたしました。
ですので、hoge_ptr++ としたときに、アドレスが 1バイトしか進まなかった場合、*hoge_ptr で読み出せる値は、意味のない値になってしまうことになります。
意味のある値を読み出すためには、int型のサイズ分 (32ビットであれば、4バイトですよね) アドレスを加算しなければいけないわけです。
こんな説明でいかがでしょうか。
No.4
- 回答日時:
皆さんの言うとおりです。
int は4バイト charは1バイトです。
このように考えるとわかりやすいです。
縦に箱がずらっと並んでいることを想像してください。
int は4バイトなのでひとつの*ptrIntにたいして4つの箱が割り当てられます。
よって初期状態で*ptrIntは[0],[1],[2],[3]がわりあてられそのうちの[0]に、上記のプログラムによると0が代入している状態です。
ここでptrInt++をすると、次の4つ箱に進みます。
よって[4],[5],[6],[7]が割り当てられ、
そのうちの[4]を示している状態です。
なので、ここでアドレスを表示すると4になるわけです。
No.3
- 回答日時:
ポインタとただのアドレスの違いはまさにこの点だと思います。
たとえば構造体のポインタでも同じで、+1すると構造体サイズ分アドレスが進みます。ポインタは構造体の先頭アドレスを指すだけでなく、そのポイントした領域のサイズ(と構造)まで表します。
この辺をおさえておけば、ポインタも扱いやすくなると思います。
No.2
- 回答日時:
>int型のポインタの場合示すデータは4バイトなので、
>ポインタ1加算は、4(バイト)加算になるということでしょうか
そういうことになります。
ptrInt++で1ずつ加算されるとどうなるか?4ずつ加算されるとどうなるか?を実際のプログラミング上でのポインタの使い方と絡めて考えるとよりポインタのことが理解できると思います。
int pnInt[2];
char pbChar[2];
として考えると分かりやすいと思います。この場合もchar*やint*で宣言したときと同じです。
こうして
&(pnInt[0])
&(pnInt[1])
&(pbChar[0])
&(pbChar[1])
のようにアドレスを見るとcharの場合はアドレスが1差なのに、intの場合は4差になります。
sizeof(int);
sizeof(char);
でintデータとcharデータの大きさを見るとそれぞれのデータサイズが分かります(4と1)(実際にはプラットフォームによってintは2など違うこともあります)。この大きさごとにアドレスも大きくなります。
int*を4ずつではなく、1ずつ大きくするには。。。
((char*)ptrInt)++;
のようにします。*ptrIntに数値を代入してアドレスを1ずつ動かして値を出力したりすると面白いかもしれません。
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
似たような質問が見つかりました
- C言語・C++・C# C言語 ポインタ 配列 2 2022/06/02 17:29
- C言語・C++・C# 関数ポインタの高速化のメリット 7 2023/05/05 20:15
- C言語・C++・C# C言語: ポインタ 5 2022/06/01 08:33
- C言語・C++・C# ポインタの型変換、どうやるんでしたっけ? 2 2022/03/28 11:00
- C言語・C++・C# 宣言する関数の形が決まっている状態で、 str1とstr2の文字列をこの順に引っ付けてstrに保存し 2 2022/05/30 18:21
- C言語・C++・C# C言語 3 2022/10/04 15:07
- C言語・C++・C# c言語でユーザ関数を利用して入力された文字列を反転させるプログラムを作りたいです。 3 2023/01/29 19:47
- C言語・C++・C# c言語配列の結合についてです。 なぜうまくいかないのでしょうか。 #include <stdio.h 4 2022/05/30 22:42
- C言語・C++・C# C pointer? or... 2 2022/03/29 00:47
- C言語・C++・C# 未解決の外部シンボル _printfが関数_mainで参照されました 1 2022/09/18 15:28
関連するカテゴリからQ&Aを探す
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
セグメントエラー
-
戻り値で構造体を返すことは可...
-
C言語のポインタに直接アドレス...
-
Run-Time Check Failure #3とい...
-
init関数の意味
-
fopne で失敗する原因
-
LPSTR型の初期化について
-
ExcelVBAでのkernel32(64bit)
-
NULLポインタが0でない処理系と...
-
PASCALとFARの意味
-
bsearch関数の呼び出しで
-
#define NULL ((void *)0) の弊害
-
C++とWIN32APIとゲームプログラ...
-
コンストラクタでnewを失敗した...
-
C言語で構造体の参照渡しができ...
-
アプリを32bitから64bit移行
-
NULLとブランクの違い
-
CImage GetBitsメソッドについて
-
不適切なポインタ
-
VC++6.0 MFC ダイアログバーを...
マンスリーランキングこのカテゴリの人気マンスリー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の意味
-
ハンドルはポインタか
-
CWnd::EnableWindow()の扱い方
おすすめ情報