![](http://oshiete.xgoo.jp/images/v2/pc/qa/question_title.png?5a7ff87)
参考書にあったプログラムなのですが、
-------------------------------------------
#include<stdio.h>
void strout(char ss[ ]);
int main(void)
{
char st[ ]="ABCDEF";
strout(st);
strout("ABab12");
return 0;
}
void strout(char ss[ ])
{
int i;
printf("ss=%s\n",ss);
i=0;
while(ss[i]){
printf("%X ",ss[i]);
++i;
}
printf("\n");
}
----------------------------------------------
------------実行結果---------------
ss=ABCDEF
41 42 43 44 45 46
ss=ABab12
41 42 61 62 31 32
-----------------------------------
初心者という事で、いろいろと疑問があるのですが、
◎1「stとして、文字配列をss[ ]に渡すのと、"ABab12"として直接文字列をss[ ]に渡すのはとは、どういうことなのかということ。そしてその時ss[ ]はどうなっているか?」
◎2「実行結果で、最初のprintfからループさせなくてもss=ABCDEF、ss=ABab12が何故2つとも表示され、2つとも16進数が表示されるのか?」
◎3「while(ss[i])だけで何故、'\0'でない間ループするという事が出来てしまうのか?」
以上のような疑問があります。
先頭のアドレスを渡すといったような説明はあるのですが、いまひとつ分かりません。
教えていただけると嬉しいです。
No.2ベストアンサー
- 回答日時:
> ◎1「stとして、文字配列をss[ ]に渡すのと、"ABab12"として直> 接文字列をss[ ]に渡すのはとは、
変数stとは、ある番地に格納された'A''B''C''D''E''F'という
char[6]型というchar配列型となります。
strout関数にこれを渡す時、配列の一番最初の場所を示す値
(先頭アドレス)を関数に与えます。
"ABab12"をstrout関数に渡す場合、この場合は、
この文字列を格納する場所を示す値が渡されるのは同じですが
文字列リテラル(文字定数)は静的メモリ領域に配置されます
ので「中身を書き換えることが許されていません」一方最初に
渡されるstは変数なので、その領域内であれば書き換えることが
可能です。
# 今回はstrout関数が中身を参照するだけで
# 書き込みを行わないので問題はありません。
> そしてその時ss[ ]はどうなっているか?」
C言語ではssのようなものを仮引数と呼びます。
仮引数は、関数が呼び出されるたびに、
与えられた引数のコピーを伴って初期化されます。
つまり、strout(st);が呼び出された時点で、
ssはstの配列の一番最初の場所を示す値で初期化され
この関数を抜けるときssは破棄され、また、
strout("ABab12");の呼び出しで、"ABab12"の
一番最初の場所を示す値で初期化され、関数を抜けるとき
破棄されます。
>◎2「実行結果で、最初のprintfからループさせなくても
> ss=ABCDEF、ss=ABab12が何故2つとも表示され、
> 2つとも16進数が表示されるのか?」
ここでのstrout関数とは呼び出すだけで文字列と
16進数字を表示してくれる機能をおもっています。
最初でstrout(st);とstrout("ABab12");で
2回呼び出されているので2つ表示されます。
>◎3「while(ss[i])だけで何故、'\0'でない間
> ループするという事が出来てしまうのか?」
C言語の文字列の終わりは'\0'であることが決められています。
'\0'は式上ではに0と等価です。
whileやifなどの条件式では0が偽(成り立たない),
0以外が真(成り立つ)ということが決まっています。
条件式のwhile(ss[i])'とは、文字列の終端が来た場合に、
while('\0')となるので、条件が成り立たなくなり、
ループを終えることができます。
説明べたで長くなりましたがこんな感じです。
>ssはstの配列の一番最初の場所を示す値で初期化されこの関数を抜けるときssは破棄され、また、strout("ABab12");の呼び出しで、"ABab12"の一番最初の場所を示す値で初期化され、関数を抜けるとき破棄されます。
これは、ssが2回以上初期化されたといった、エラーが出ないのは、「関数を抜けるときssが破棄される」からといった感じだからでよいのでしょうか?
No.4
- 回答日時:
> これは、ssが2回以上初期化されたといった、
> エラーが出ないのは、「関数を抜けるときssが破棄される」
> からといった感じだからでよいのでしょうか?
初期化と書きましたが様はmainから渡された式の結果の代入です。
「破棄されるから」というよりは、strout関数に指定された引数が、
ssという名前に置き代わる以外は、1回目に呼び出された時のssと
2回目に呼び出されたssには関係が無いというか、分けて
考えるべきだということです。
#ちょっと説明下手なので語弊を招くかもしれませんが。
>1回目に呼び出された時のssと2回目に呼び出されたssには関係が無いというか、分けて考えるべきだということです。
かなり納得いたしました。ありがとうございます。
No.3
- 回答日時:
◎1
mainでは、どっちも「文字列の先頭のアドレスだけ」を渡しています。
stroutでは「文字列の先頭アドレスだけ」を受け取っています。
配列や文字列の全部をそのまま受け渡ししている訳ではありません。
簡単に言うと、mainからは「文字列のある場所だけ教えるから、教えた場所から取り出して使ってね」と関数を呼び出します。
呼ばれたstroutは「なるほど、ここにあるのか。ここから取り出して使おう」と、教えられた場所を信じて動きます。
配列そのものや、文字列そのものは、受け渡ししていません。
実は
void strout(char ss[ ])
{
中身略
}
と書くと
void strout(char *ss)
{
中身略
}
と書いたのと同じなのです。
◎2
質問が日本語ではないようです。日本語で大丈夫なので、日本語で書いて下さい。
◎3
条件式は「非0なら真、0なら偽」です。
'\0'は、数値的には「0」なので
「非0なら真、0なら偽」
と
「非'\0'なら真、'\0'なら偽」
は等価です。
なので
while(ss[i])
と
while(ss[i] != '\0')
は等価です。
ただし、前者の方が判断する時間が短くなる場合があります。
while(ss[i])
と
while(ss[i] != '\0')
が同じ意味ということかなり納得いきました。
ありがとうございます。
No.1
- 回答日時:
◎1、文字型配列変数に一時格納するか、文字定数するかの違いで
処理結果上違い。はありません。
ss[]とは変数型であって、変数名としてはssです。
strout(st); ----ssの値 ABCDEF
strout("ABab12"););----ssの値 ABab12
◎2、ABCDEF、ABab12と表示されるのprintf文で%sとしている為。
16進数で表示されるのはprintf文で%Xとしている為。
文字として表示するのであれば、%cとする。
◎3、文字列の末端は必ず\0(ヌル)文字である決まりごとだからです。
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
似たような質問が見つかりました
- C言語・C++・C# c言語の問題の説明、各所ごとに 5 2023/07/26 11:03
- C言語・C++・C# 宣言する関数の形が決まっている状態で、 str1とstr2の文字列をこの順に引っ付けてstrに保存し 2 2022/05/30 18:21
- C言語・C++・C# c言語配列の結合についてです。 なぜうまくいかないのでしょうか。 #include <stdio.h 4 2022/05/30 22:42
- C言語・C++・C# c言語でユーザ関数を利用して入力された文字列を反転させるプログラムを作りたいです。 3 2023/01/29 19:47
- C言語・C++・C# バイナリファイルをコピーするのにかかる時間を測りたいのですが実行するとFatel error:gli 2 2022/11/03 01:10
- Excel(エクセル) VBAで組み合わせ算出やCOUNTIFSの処理を高速化したいです。 4 2022/04/07 02:38
- PHP 【スプレッドシート】順位のつけ方 2 2022/08/17 13:27
- C言語・C++・C# プログラミングの授業の課題です 1 2023/01/17 22:15
- Visual Basic(VBA) Excel VBAでAA(BBB) → BBB.AA に置換したい 2 2022/10/30 13:59
- HTML・CSS 【HTML】【CSS】【Swiper】 元の画像は横1200×縦600なのですが、実際のサイト上に反 5 2022/07/16 13:57
関連するカテゴリからQ&Aを探す
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
C++で入力した文字列から数字を...
-
TCL言語で文字列検索方法を教え...
-
%dなどの違い
-
アルファベットをカウント、
-
nullと""、\\0とEOFの違いにつ...
-
C言語の勉強しています。すみま...
-
[C++]WCHARの1文字目しか表示で...
-
文字列にある特定文字の数
-
プログラムによく出てくるst...
-
Shift_JIS(16進)を文字に変換す...
-
C言語についてです学籍番号、名...
-
ポインターのポインターについ...
-
#include <stdio.h> int main(v...
-
sprintf関数での文字列変換につ...
-
ソースコードの間違い (C言語)
-
char型配列の最大要素数
-
NUMERICチェック
-
WSH(VBS)でJSONの文字列を読み...
-
[Excel VBA]デフォルトプロパティ
-
16進数を2文字ずつ配列に格納し...
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
プログラムによく出てくるst...
-
nullと""、\\0とEOFの違いにつ...
-
TCL言語で文字列検索方法を教え...
-
C#でstringをポインタとして渡す
-
C++で入力した文字列から数字を...
-
%dなどの違い
-
WSH(VBS)でJSONの文字列を読み...
-
16進数を2文字ずつ配列に格納し...
-
シリアル通信で0x00を送信した...
-
_tcscpy_s(wcscpy_s)の第二引数...
-
構造体→文字列→構造体 をする方法
-
VBA-DLLの引数受け渡しについて
-
[C++]WCHARの1文字目しか表示で...
-
数字の入った配列をファイルへ...
-
VB6.0でのバイナリデータの扱い...
-
引用符と二重引用符
-
こんなことって可能なのですか...
-
char型配列の最大要素数
-
sprintf関数について教えて下さ...
-
C言語の課題で困っています;
おすすめ情報