同じような質問ばっかりたて続けにしてしまってすみません・・
あの,以下のような例の時↓
------
{
char array[7];
char *ptr;

strcpy(array, "abcdef");

ptr = &(array[0]);

printf(" array = %s\n ptr = %s\n", array, ptr);
}
------
これを実行したら、
array = abcdef
ptr = abcdef
となりますが、ポインタとして宣言してるptrから文字列を得たい時は
*ptr と書くんではないのでしょうか?
%s のように出力形式のところを指定をするだけで
文字列で表示してくれるのはなぜですか?
上の例のように書くのが正しいのでしょうか

このQ&Aに関連する最新のQ&A

A 回答 (6件)

%dや%xは、引数の値を表示する機能です。


%sは引数の値をアドレスとみなして、その先にあるメモリーを
0x00が現れるまで文字列として表示する機能です。

char *ptr;という定義があって、実行文中で*ptrと書くと
「ptrのさすメモリー」の中にあるデーターの値を意味します。
このとき、型定義にしたがって最終的な値はcharとして扱われます。
ただ単にptrと書くと、変数の型定義にしたがってchar *の意味、
つまり「「charの入っているメモリー」のアドレス」の意味になります。

printf("%s",*ptr);の意味は、
printf("引数をアドレスとみなしその先のメモリーを表示する",
  「ptrのさすメモリーの中のデーター」をアドレスとして使う);

printf("%s",ptr);の意味は
printf("引数をアドレスとみなしその先のメモリーを表示する",
  ptrそのもの(←つまり"abcdef"の入っているメモリーのアドレス) );

ちょっと難しいですが、仕様にたちかえって説明してみました。
最初はこんがらがりますが、がんばってください。
    • good
    • 0
この回答へのお礼

すごく頭がこんがらまってます。はあ。。むずかしいですね・・。もっと勉強します。

お礼日時:2001/03/02 11:31

printf(" array = %s\n ptr = %s\n", array, ptr);


を良く見て下さい。
array は何と等価でしょうか?

配列を配列名だけで書いたときは、その値は配列の先頭アドレスをさします。
つまり、arrey は &arrey[0] とは同じアドレス(つまり同じ値です)を差し
ています。

また printf のフォーマット部分で %s は他の方も書かれているように、
「ポインタの指し示すアドレスから\0 が見つかるまでを文字列として表示する。」
というprintf への指示です。

そのため、yuki7505 さんの書いたプログラムは、yuki7505 さんの書かれたような
結果が返ってきたのです。

また、*ptr とした場合は arrey 配列の先頭の文字 "a" の値が得られます。

これは、char *型の変数は はコンパイラから見てchar 配列のポインタなのか
char 変数のポインタなのかはまったく区別つかないし、区別してはいけない
ものだからです。そうしないと、配列用のポインタ、1文字変数用のポインタ・・・
ととんでもない数の型を言語仕様で作らなければならなくなります。

それで、*ptr と書いた場合は char 型の値が帰ってくるのです。では
*ptr が差すものが、配列だったらどうするの?と言われると、
「それはプログラマがそれを配列として扱い処理する。」
と言うことになります。

ということでたぶん、yuki7505 さんは、
printf("arrey = %s\n ptr = %08x\n",arrey,ptr);

として、文字列とそのアドレスを表示されることを期待していたのではと思い
ますがどうでしょうか?
    • good
    • 0
この回答へのお礼

そう期待してたんですが違うんですね。もっともっと勉強します。ありがとうございました。

お礼日時:2001/03/02 11:30

C言語を勉強している人が陥りやすいワナにかかりましたね


C言語というものはシンプルですからもっと客観的に考える必要があります
それぞれの変数にどんな値が入っているかを良く考えながらもう一度トレース
してみてはいかがでしょうか
ちなみにこのプログラムでは

ptr = &(array[0]);

の処理の結果 ptr == array となります
( ただし array は変数ではないですが
代入できない char * 変数と考えればOKです )
ですからこの行の処理は

ptr = array;

とやっていることはまったく同じです
この行に置き換えてこのプログラムを見直してみてください
・・・いかがでしょう、少しはわかりやすくなったのでは・・・?
    • good
    • 0
この回答へのお礼

ありがとうございます。色々試してみます。

お礼日時:2001/03/02 11:28

失礼ですが、もう一度C言語の教科書を


読み直しましょう。
まず、ポインタの前に文字型以外の配列の勉強を
して正しい理解をしてください。
(「文字列」はちょっと特殊なので、、、)

「*ptr」の「*」は「ptr」が参照する先のアドレス
の中身(特定の1バイト)を参照するための演算子です。
ですから、*(ptr+1)とすれば「b」を指します。

printf(" array = %s\n ptr = %s\n", array+1, ptr+1);
とすれば、
array = bcdef
ptr = bcdef
と表示されます。
array自身はアドレスを指していますので
「array+1」で「array」から「sizeof(char)*1」分
だけアドレスがインクリメントされるため
「*(array+1)」は「array[1]」と等価となり、「array+1」は「&array[1]」と等価となります。

「%s」書式指定子には参照先のアドレスを指定します。
「%s」書式指定子は指示されたアドレスから開始
され、「\0(null文字)」までのバイト列を単純に
表示するだけの機能です。
「ptr+1」も同様で「ptr」の参照先は「&array[0]」
なので「ptr+1」で「&array[1]」と等価となります。
    • good
    • 0
この回答へのお礼

ありがとうございます。

お礼日時:2001/03/02 11:26

 %s は、指定された変数をポインタとして見るからです。

    • good
    • 0
この回答へのお礼

ありがとうございます。

お礼日時:2001/03/02 11:26

*ptrで宣言した場合は、文字列表示する場合はptrと書くのが正しいのです。


ptrが文字列の先頭ポインタをさします。
    • good
    • 0
この回答へのお礼

ありがとうございます。

お礼日時:2001/03/02 11:25

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!

このQ&Aを見た人が検索しているワード

このQ&Aと関連する良く見られている質問

Qchar c = 'a'; char h[1] = c; エラー

char型のものを char[]型に代入したいです。

char c = 'a';
char h[1] = c;

として、

h[0] は \x97
h[1] は \x00

にしたいです。
型変換の方法を教えてください。

Aベストアンサー

とりあえず、確認を。

C では、'a'の表す値は 0x61 = 97 であって、 \x97 ではないと思います。
(\xnnn を、十六進数の意味に取りましたが、あってますでしょうか?
この場合、C では通常 0xnnn のように書くと思います。)
ので、 これは 0x61 のことをおっしゃっていると仮定します。

> char h[1] = c;
っと、これではたぶんコンパイルが通りません。

char h[1] = {c};

のように、配列であることを明示して代入してください。
この式では、前半でh という名前の、*長さ1 の* char の配列変数を確保します。
後半で、その中を初期化しています。
添え字は 0 からはじまるので、この場合、h[0] に c の内容が代入されます。
1個しか場所を確保していないので、 h[1] の位置のデータは内容が不定です。
文字列として h を扱いたいのであれば、 C の文字列には終端として 0 が必要ですから、
char c = 'a';
char h[2] = { c, '\0'};

のような書き方が必要になります。
これで、お望みのデータになると思います。

とりあえず、確認を。

C では、'a'の表す値は 0x61 = 97 であって、 \x97 ではないと思います。
(\xnnn を、十六進数の意味に取りましたが、あってますでしょうか?
この場合、C では通常 0xnnn のように書くと思います。)
ので、 これは 0x61 のことをおっしゃっていると仮定します。

> char h[1] = c;
っと、これではたぶんコンパイルが通りません。

char h[1] = {c};

のように、配列であることを明示して代入してください。
この式では、前半でh という名前の、*長さ1 の* char の配列変数...続きを読む

Qint i,j; \n i=0,j=5;

int i,j;
i=0;
j=5:
と書いてあるソースは普通ですが、
int i,j;
i=0,j=5:
と書いてあるソースもあります。
後者はC++の正しい書式ですか?

カンマ演算子というのは後者のカンマのことですか?

Aベストアンサー

 正しい書式です。

i=0,j=5;
 における、「,」をカンマ演算子といいます。2項の演算子です。カンマで区切られた演算を「左から順番に」実行し、最後の演算を結果として返します。
 したがって、例の文であれば、i=0を実行し、次にj=5を実行。そして、j=5の結果の5を結果として返します。
 ・・・
 が、本来的には、あまり、例のような使い方はしませんね。よく見られるのは、次のような場合です。

 for (i=0,j=0 ; i < 50 ; ++i,++j) {

 のような形でよく見られます。for文の各式は、一つの式でなければならないので、こんな書き方をするわけです。初期化と更新部が一つにまとまり、ループが読みやすくなるのが利点かな。

Qcharと%c , %s の関係について

char型の変数の扱いで悩んでいます。
具体的には以下の二つのプログラムの差異についてです。

----------------------
char c;

scanf("%c", &c);
printf("%c\n", c);

-----------------------
char c;

scanf("%s", &c);
printf("%s\n", &c);

-----------------------


上のプログラムは正しいと思うのですが、下のプログラムが正しいのかどうか、わかる方に教えていただきたいと思い質問させていただきました。

どちらのプログラムも問題なく動作します。
僕自身は 下のプログラムの printf 関数については間違った使い方なのではないかと思っています。

scanf("%s", &c) は入力された文字のうち、終端文字の手前までの文字を引数のポインタが示すオブジェクトへ順に格納していく関数だと理解しているので、入力された文字が一文字だった場合、&cの示すオブジェクトに文字が代入されると考えたからです。

逆に printf("%s", &c) は、&cの示すオブジェクトから”ヌル文字”の手前までの文字列を順に表示する関数だと理解しているので、問題なく動作しているのは&cで示されるオブジェクトの後ろの領域が偶然'\0'だったからではないかと考えたからです。

何かの本で、未使用の領域は0である確率が高いという記述をみたことがあり、'\0'は0と同じだということなので問題なく動作する率が高いのではないかと思っています。


僕の考え方がどの程度正しくて、正確にはどうなのかを教えて欲しいです。


ちなみに、

-----------------------
char c;
char str[100];

scanf("%s", str);
scanf("%c", &c);
------------------------

と書くと c には改行文字が代入されてしまいます。
scanf("%s", str);
において"aasssdd "と最後に空白を入れると
c には空白文字が代入されます。

しかし、
--------------------------
char str1[100];
char str2[100];

scanf("%s", str1);
scanf("%s", str2);
--------------------------
においては、
scanf("%s", str1);
で "asdfg "と最後に空白を入れても次のstr2が空白で始まることはありません。


この辺りの処理がどのような法則で実行されているのかが分かりづらくて悩んでいます。
おそらく、
scanf("%s", str);
の場合には最初の文字が空白や改行文字でも、その次に有効な文字があればそれらの改行や空白を無視するのではないかと思っています。


分かる方がいましたら回答をよろしくお願いします。

char型の変数の扱いで悩んでいます。
具体的には以下の二つのプログラムの差異についてです。

----------------------
char c;

scanf("%c", &c);
printf("%c\n", c);

-----------------------
char c;

scanf("%s", &c);
printf("%s\n", &c);

-----------------------


上のプログラムは正しいと思うのですが、下のプログラムが正しいのかどうか、わかる方に教えていただきたいと思い質問させていただきました。

どちらのプログラムも問題なく動作します。
僕自身は 下...続きを読む

Aベストアンサー

> char c;
> scanf("%s", &c);
char c では1文字分の領域しか確保されていないので、
1文字以上の文字列を無理矢理格納すると
他のデータが存在しているかもしれない領域を書き換えてしまいます。(メモリ破壊)

なお、'\0'はscanfが(本来書き込んではいけない領域に対してですが)書き込んでいます。


> と書くと c には改行文字が代入されてしまいます。
最初のscanfが改行文字を読み込んでいないからです。
以下のページに書かれている内容と本質的には同じ。
http://www9.plala.or.jp/sgwr-t/c/sec05.html#s5-

> 最初の文字が空白や改行文字でも、その次に有効な文字があればそれらの改行や空白を無視するのではないかと思っています。
そう考えて問題ないと思います。

Qchar *str; と char* str;

char *str; と char* str;
どっちも同じことを意味しているんですか?

Aベストアンサー

同じことを指している、というのは、先の回答の通りです。

また、ひとつの宣言で変数を複数宣言したときに、char* str という表記は間違い
易いじゃないか、ということが言われているのも事実です。実際、いろいろな C のソースを
見ていても、まずアスタリスクを型につけて書くのは、まずお目にかかれません。

ただ C++ では、char* str という宣言も良く使われています。

C++ に限らずオブジェクト指向の言語は、強く型を意識するので、「文字のポインタ型」と
いう意味で、まとめて書く方が馴染むのでしょう。ちなみにそういう風な人たちは

char *str1, *str2;

とは、書けない体になっています。

char* str1;
char* str2;


変数の宣言だと、C に慣れていれば、char* str というのはちょっと違和感があるのは
私も分かりますが、関数のプロトタイプ宣言だと、どちらの方がすっきりしますか?

extern char *memcpy(char *, const char *);

extern char* memcpy(char*, const char*);


# まあ、どっちが正しい、っていうんじゃ無いんですよね

同じことを指している、というのは、先の回答の通りです。

また、ひとつの宣言で変数を複数宣言したときに、char* str という表記は間違い
易いじゃないか、ということが言われているのも事実です。実際、いろいろな C のソースを
見ていても、まずアスタリスクを型につけて書くのは、まずお目にかかれません。

ただ C++ では、char* str という宣言も良く使われています。

C++ に限らずオブジェクト指向の言語は、強く型を意識するので、「文字のポインタ型」と
いう意味で、まとめて書く方が馴染む...続きを読む

Qfor(int i = 100, long n = 1; i > n/3i; i++)

for(int i = 100, long n = 1; i > n/3i; i++)
のように、初期設定で型の違う変数を宣言したいんだけど
C++ではこんなふうに2つ以上の型を宣言してはいけないんですか?

Aベストアンサー

,

コンマ演算子の原理です。
forの初期化文で "," で区切れるのは値を返す文だけです。
よってintステートメントもlongステートメントも値を返さないので、この文では使用できません。

というか、むしろ、intステートメントの第2引数としてlongが認識されてしまいます。
外で

int i; long n;

とし

for(i = 0, n = 0; hoge; hoge)

なら可能です。


人気Q&Aランキング

おすすめ情報