ページ 1 / 1
%sで表す時のアドレス
Posted: 2010年11月30日(火) 01:26
by C初心者
はじめまして。
自分はC言語初心者でして、今独学で「猫でも分かるC言語プログラミング」という本を参考に読み進めているのですが、どうしても解決できない疑問と衝突してしまいましたので質問掲示板を利用させていただきます。
どうかどなたかご教授ください
コード:
#include <stdio.h>
main()
{
char a[10] = "abcde";
char *p;
p = a;
printf("%s, %s\n", a, p); /* ① */
printf("%d, %d\n", a, p); /* ② */
}
このコードについてなのですが
実行結果は自分のパソコンでは
abcde, abcde
1245012, 1245012
となりました。
②においては当然aはa[0]の格納されているアドレスを表すはずだと理解できたのですが
①のaが示す結果がabcdeとなるのが何故なのかがどうしても分かりません。
アドレスがabcdeということなのでしょうか?
それとも%sで表す時は特別に全て表示するという規則があったのでしょうか(なかったように思うのですが)。
どなたかお願いします。
Re: %sで表す時のアドレス
Posted: 2010年11月30日(火) 01:47
by bitter_fox
C初心者 さんが書きました:
コード:
#include <stdio.h>
main()
{
char a[10] = "abcde";
char *p;
p = a;
printf("%s, %s\n", a, p); /* ① */
printf("%d, %d\n", a, p); /* ② */
}
②においては当然aはa[0]の格納されているアドレスを表すはずだと理解できたのですが
①のaが示す結果がabcdeとなるのが何故なのかがどうしても分かりません。
アドレスがabcdeということなのでしょうか?
それとも%sで表す時は特別に全て表示するという規則があったのでしょうか(なかったように思うのですが)。
%sを指定したときは、引数に渡されたアドレスから'\0'文字までの文字列が出力されます。
御指摘どうり、このときのaは&a[0]と同義になり、アドレスの指す文字は以下のようになります。
a[0]のアドレスは、質問にあわせて、1245012とします。
1245012:'a'
1245013:'b'
1245014:'c'
1245015:'d'
1245016:'e'
1245017:'\0'
よって、'a'~'\0'までの、"abcde"が出力されたというわけです
Re: %sで表す時のアドレス
Posted: 2010年11月30日(火) 03:45
by ゆーずぃ
C初心者 さんが書きました:
コード:
#include <stdio.h>
main()
{
char a[10] = "abcde";
char *p;
p = a;
printf("%s, %s\n", a, p); /* ① */
printf("%d, %d\n", a, p); /* ② */
}
このコードについてなのですが
実行結果は自分のパソコンでは
abcde, abcde
1245012, 1245012
となりました。
②においては当然aはa[0]の格納されているアドレスを表すはずだと理解できたのですが ー以下略ー
質問者さんがアドレスだと思っている1245012はアドレスではありません。
%dで表せるのは10進整数です。ですので、16進数で表されたアドレスを10進数に変換しているだけです。
アドレスを表わしたいのなら%pです。
試しに以下のコードを書いてみましょう。
コード:
#include <stdio.h>
main()
{
char a[10] = "abcde";
char *p;
p = a;
printf("%p, %d\n", p, p); /* ② */
}
2つの数値が出てくるはずです。
%pの数値を16進数→2進数に
%dの数値を10進数→2進数に
それぞれ基数変換してみましょう。2つの数値を2進数に直すと同じ値になることが確認できるはずです。
アドレスの表し方の質問ではないようですが、これは知っておいた方がいいです。
そして一つ気になったのですが、質問者さんは変換指定子の理解が足りない気がします。
アドレスを渡せばどの指定子でもアドレスを表示してしまったら大変です。
全てのデータは2進数で出来ています。変換指定子はそれをどう料理して表示するかの指定です。
%sは文字列、%cは文字、%d,iは10進符号付き整数…といったように同じ数値をそれぞれの指定によって切り替えます。
最初の質問の%sは、文字列として表示しろといっているのですから、何を渡しても文字列として表示しようとします。
そのため、%sにabcde\0の文字列を渡せば、abcdeの文字列を表示するのは当たり前と言えます。
Re: %sで表す時のアドレス
Posted: 2010年11月30日(火) 07:36
by C初心者
お早い回答ありがとうございます。ゆーずぃさんの変換子の説明はとてもよく理解できました。ありがとうございます。
しかし質問したかったことがどうもまだよく分かりません。
1245012:'a'
1245013:'b'
1245014:'c'
1245015:'d'
1245016:'e'
1245017:'\0'
とのご説明頂けましたが、これは左はアドレス(10進で表したときの)、右はその値ですよね。
どうしてアドレスを指定しているのに値が表示されるのでしょう?それがわからないのです。
ゆーずぃさんの説明から推測するとアドレスを%sで表すのには無理があるのでやむを得ず値を、という事でしょうか?それだとしてもエラーが出て処理されずに終わるのかと思っていたのですが…
何度も申し訳ありませんがどなたかご教授ください
Re: %sで表す時のアドレス
Posted: 2010年11月30日(火) 09:40
by non
C初心者 さんが書きました:どうしてアドレスを指定しているのに値が表示されるのでしょう?それがわからないのです。
すでにbitter_fox さんが書かれているとおり、%s は与えられたアドレスから'\0'が現れるまでの文字列を出力する仕様に
なっているからです。
文字列は、どこが終わりかわからないと困るので、文字列の終端に'\0'を入れるという仕様になっています。
そうすれば、文字数がわからなくても先頭のアドレスの中身から順番に'\0'になるまで出力すればよいからです。
Re: %sで表す時のアドレス
Posted: 2010年11月30日(火) 12:34
by softya(ソフト屋)
分かりやすい形で出力するプログラムに直してみました。
納得出来るまで、いろいろプログラムを変えて実行してみてください。
コード:
#include <stdio.h>
int main()
{
int i;
char a[10] = "abcde";
char *p;
p = a;
printf("文字列表示 %s, %s\n", a, p); /* ① */
printf("文字列アドレス(10進) %d, %d\n", a, p); /* ② */
printf("文字列アドレス(16進) 0x%p, %p\n", a, p); /* ③ */
// アドレスと文字の表示
for( i=0 ; i<10 ; i++ ) {
if( a[i] < 0x20 ) { //制御文字コードは表示しない。
printf("アドレス=制御文字(16進文字コード) %p=_(0x%02x)\n", &a[i], a[i] ); /* ④ */
} else {
printf("アドレス= 文字(16進文字コード) %p=%c(0x%02x)\n", &a[i], a[i], a[i] ); /* ④ */
}
}
}
実行結果は次のようになります。
コード:
文字列表示 abcde, abcde
文字列アドレス(10進) 5175872, 5175872
文字列アドレス(16進) 0x004EFA40, 004EFA40
アドレス= 文字(16進文字コード) 004EFA40=a(0x61)
アドレス= 文字(16進文字コード) 004EFA41=b(0x62)
アドレス= 文字(16進文字コード) 004EFA42=c(0x63)
アドレス= 文字(16進文字コード) 004EFA43=d(0x64)
アドレス= 文字(16進文字コード) 004EFA44=e(0x65)
アドレス=制御文字(16進文字コード) 004EFA45=_(0x00)
アドレス=制御文字(16進文字コード) 004EFA46=_(0x00)
アドレス=制御文字(16進文字コード) 004EFA47=_(0x00)
アドレス=制御文字(16進文字コード) 004EFA48=_(0x00)
アドレス=制御文字(16進文字コード) 004EFA49=_(0x00)
Re: %sで表す時のアドレス
Posted: 2010年12月01日(水) 00:16
by paw
ご回答ありがとうございました。
皆さんのおかげでなんとなくではありますが理解できたような気がします。
そういう仕様なのですね。
アドレスを扱うときは%pを使うことを徹底してみます。
期待していた以上に収穫があったように思います。
回答してくださった皆さん本当にありがとうございました。
私事となりますが
この掲示板と回答者の皆様のあたたかさに魅了され、pawという名前でユーザー登録させていただきました。
もちろん自分で解決できるように全力を尽くしますがどうしても解決できないときはまた回答いただけますと幸いです。
皆さんご回答ありがとうございました。以降なにとぞよろしくお願いします。