こんにちはゲストさん。会員登録(無料)して質問・回答してみよう!

解決済みの質問

ポインタ変数のサイズ

 いろいろC言語のことを知りたくて、次のソースを作って動かしてみました。

★ソース(□はタブ)
◆◆◆◆◆
#include <stdio.h>
#include <stdlib.h>

int main(void)
{
□char *s1;
□int *s2;

□s1 = (char *)malloc(1000);
□s2 = (int *)malloc(1000);

□printf("sizeof s1 = %d\n", sizeof s1);
□printf("sizeof s2 = %d\n", sizeof s2);

□printf("sizeof *s1 = %d\n", sizeof *s1);
□printf("sizeof *s2 = %d\n", sizeof *s2);

□printf("s1 = %d\n", s1);
□printf("s2 = %d\n", s2);

□printf("*s1 = %d\n", *s1);
□printf("*s2 = %d\n", *s2);

□return EXIT_SUCCESS;
}
◆◆◆◆◆

★実行結果1
◆◆◆◆◆
sizeof s1 = 4
sizeof s2 = 4
sizeof *s1 = 1
sizeof *s2 = 4
s1 = 1323000
s2 = 1324008
*s1 = -60
*s2 = 1310916
◆◆◆◆◆

★実行結果2
◆◆◆◆◆
sizeof s1 = 4
sizeof s2 = 4
sizeof *s1 = 1
sizeof *s2 = 4
s1 = 11087864
s2 = 11088872
*s1 = -60
*s2 = 11075780
◆◆◆◆◆

★実行結果3
◆◆◆◆◆
sizeof s1 = 4
sizeof s2 = 4
sizeof *s1 = 1
sizeof *s2 = 4
s1 = 1519608
s2 = 1520616
*s1 = -60
*s2 = 1507524
◆◆◆◆◆

 OSはWindows Vista、コンパイラはMS Visual Studio 2010 コマンドプロンプトです。次の疑問についてご教授頂きたく、お願い致します。

(1)“sizeof s1”、“sizeof s2”の値が共に4となるのはなぜか。
 char型へのポインタ、int型へのポインタとして宣言したs1、s2のサイズが同じ4になる理由が、どうしても分かりません。
(動かす前の予想は、でたらめな値になるかと思っていましたが)

(2)“s1”、“s2”、“*s2”の値が毎回でたらめな値になったのに対して、“*s1”の値が毎回“-60”になったのはなぜか。

 ポインタでつまずいており、いろいろ実験して体で理解したいと思っています。どうぞよしくお願い致します。

投稿日時 - 2013-11-12 21:52:41

QNo.8344983

困ってます

質問者が選んだベストアンサー

1) ポインタ変数とは、アドレスを保持する変数です。

 ですから、ポインタの先に、int であろうが、char であろうが、平安京エイリアンであろうが、なにが、ぶらさがっていても、ポインタ変数の中身は、アドレスです。

 ですから、 sizeof s1, sizeof s2 は、そのマシンのアーキテクチャできまる、アドレスを保持するサイズです。4ということは、32bitマシンなのでしょう。

2)

printf("s1 = %d\n", s1);

 は、コンパイラにとっては、

 s1で、ポイントされる1バイトを符号付きcharとし、
それを、intに拡張して、printfの第2引数として、渡す、ということです。
 printfは、第1引数の書式指定に従い、第2引数を、intとして、プリントする

 ということです。それで、-60 と表示されたのは、元の1バイトも、-60.
すなわち、-60 とは、11010000 == 0xd0 が、s1のポイントしているアドレスにあったということです。

 mallocで割り当てられる領域は、ヒープ領域と呼ばれますが、ここは、初期化していない限り、値について
仮定を置くことは出来ません。同じコンパイラ環境で、ヒープの先頭なので、その辺は、0xd0になっていることが
多いといことだけの話です。s1とs2のallocの順番を逆にすれば、s2の方が定値になりやすいでしょう。

 ですから、ちがう環境、たとえば、cygwin や、bcc32 あるいは、Xcode/Macなどでは、同一ソースでも、違う結果になるでしょう。

投稿日時 - 2013-11-12 23:43:06

お礼

xpd154様、誠にありがとうございます。非常に明快に、また丁寧にご教授くださいました。大変感謝いたします。よく勉強します。ありがとうございました。

投稿日時 - 2013-11-14 21:44:10

このQ&Aは役に立ちましたか?

0人が「このQ&Aが役に立った」と投票しています

回答(4)

ANo.4

あと一応突っ込んでおくと char 自体が符号付きか符号なしかは処理系定義です. Visual Studio (というか Visual C) では標準は符号付きですが, コンパイラオプションで符号なしにもできます.

投稿日時 - 2013-11-13 14:49:54

お礼

 処理系依存ですか。またいろいろ実験してみます。ありがとうございました。

投稿日時 - 2013-11-14 21:47:05

再び、#1の回答者です。間違い指摘ありがとう>#2

#1の回答の後半は、

□printf("*s1 = %d\n", *s1);


 についての解説のことです。

投稿日時 - 2013-11-13 09:12:06

お礼

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

投稿日時 - 2013-11-14 21:45:54

ANo.2

printf("s1 = %d\n", s1);
で「s1で、ポイントされる1バイト」はでてきませんぜ>#1. 単に
変数 s1 に入っている値を int と思って出力する
だけ. ちなみにポインタ変数の値を %d で出すのは未定義動作だから, 突然 PC で平安京エイリアンが動きだしても文句はいえない (と #1 に乗ってみる).

投稿日時 - 2013-11-13 00:00:26

お礼

 補足をありがとうございました。

投稿日時 - 2013-11-14 21:45:13