%sで表す時のアドレス

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
C初心者

%sで表す時のアドレス

#1

投稿記事 by C初心者 » 13年前

はじめまして。
自分は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で表す時は特別に全て表示するという規則があったのでしょうか(なかったように思うのですが)。

どなたかお願いします。

アバター
bitter_fox
記事: 607
登録日時: 13年前
住所: 大阪府

Re: %sで表す時のアドレス

#2

投稿記事 by bitter_fox » 13年前

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"が出力されたというわけです

アバター
ゆーずぃ
記事: 62
登録日時: 13年前
住所: 埼玉県

Re: %sで表す時のアドレス

#3

投稿記事 by ゆーずぃ » 13年前

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の文字列を表示するのは当たり前と言えます。

C初心者

Re: %sで表す時のアドレス

#4

投稿記事 by C初心者 » 13年前

お早い回答ありがとうございます。ゆーずぃさんの変換子の説明はとてもよく理解できました。ありがとうございます。
しかし質問したかったことがどうもまだよく分かりません。

1245012:'a'
1245013:'b'
1245014:'c'
1245015:'d'
1245016:'e'
1245017:'\0'
とのご説明頂けましたが、これは左はアドレス(10進で表したときの)、右はその値ですよね。
どうしてアドレスを指定しているのに値が表示されるのでしょう?それがわからないのです。
ゆーずぃさんの説明から推測するとアドレスを%sで表すのには無理があるのでやむを得ず値を、という事でしょうか?それだとしてもエラーが出て処理されずに終わるのかと思っていたのですが…

何度も申し訳ありませんがどなたかご教授ください

non
記事: 1097
登録日時: 13年前

Re: %sで表す時のアドレス

#5

投稿記事 by non » 13年前

C初心者 さんが書きました:どうしてアドレスを指定しているのに値が表示されるのでしょう?それがわからないのです。
すでにbitter_fox さんが書かれているとおり、%s は与えられたアドレスから'\0'が現れるまでの文字列を出力する仕様に
なっているからです。
文字列は、どこが終わりかわからないと困るので、文字列の終端に'\0'を入れるという仕様になっています。
そうすれば、文字数がわからなくても先頭のアドレスの中身から順番に'\0'になるまで出力すればよいからです。
non

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 13年前
住所: 東海地方
連絡を取る:

Re: %sで表す時のアドレス

#6

投稿記事 by softya(ソフト屋) » 13年前

分かりやすい形で出力するプログラムに直してみました。
納得出来るまで、いろいろプログラムを変えて実行してみてください。

コード:

#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)
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

paw
記事: 15
登録日時: 13年前

Re: %sで表す時のアドレス

#7

投稿記事 by paw » 13年前

ご回答ありがとうございました。
皆さんのおかげでなんとなくではありますが理解できたような気がします。

そういう仕様なのですね。
アドレスを扱うときは%pを使うことを徹底してみます。

期待していた以上に収穫があったように思います。
回答してくださった皆さん本当にありがとうございました。



私事となりますが
この掲示板と回答者の皆様のあたたかさに魅了され、pawという名前でユーザー登録させていただきました。
もちろん自分で解決できるように全力を尽くしますがどうしても解決できないときはまた回答いただけますと幸いです。
皆さんご回答ありがとうございました。以降なにとぞよろしくお願いします。

閉鎖

“C言語何でも質問掲示板” へ戻る