質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

for

for文は、様々なプログラミング言語で使われている制御構造です。for文に定義している条件から外れるまで、for文内の命令文を繰り返し実行します。

デバッグ

デバッグはプログラムのバグや欠陥を検知し、開発中のバグを取り除く為のプロセスを指します。

ループ

ループとは、プログラミングにおいて、条件に合致している間、複数回繰り返し実行される箇所や、その制御構造を指します

Q&A

解決済

5回答

2399閲覧

デバッグでのforループによるstr[]の中身の変化。

carnage0216

総合スコア194

C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

for

for文は、様々なプログラミング言語で使われている制御構造です。for文に定義している条件から外れるまで、for文内の命令文を繰り返し実行します。

デバッグ

デバッグはプログラムのバグや欠陥を検知し、開発中のバグを取り除く為のプロセスを指します。

ループ

ループとは、プログラミングにおいて、条件に合致している間、複数回繰り返し実行される箇所や、その制御構造を指します

0グッド

0クリップ

投稿2021/08/06 00:10

編集2021/08/06 06:03
#include <stdio.h> #include <string.h> int main(void) { char str[] = "str == NULL ? \"(NULL)\": str"; char* p, * q; int ch; p = str; for (;;) { for (q = p; !(*q == '?' || *q == ':' || *q == 0); q++); ch = *q; *q = 0; printf("|%s|\n", p); if (ch == 0) break; p = q + 1; } }

疑問があります。なぜforループの二周目以降のデバッグでのstr[]の中身はstr == NULLであるのに、一週目のみstr[]の中身はstr == NULL ? "(NULL)": strであるかについてです。
y_waiwaiさんに**過去にforの一週目のカッコの中身、すなわち(q = p; !(*q == '?' || q == ':' || q == 0); q++)のq++は働かないと聞きました。
私なりの推測としてq++が働かなったためにqには0や値すらも入らないためp = q + 1;が動かず、一週目のデバッグのstr[]の中身はstr == NULL ? "(NULL)": strなのかなと考えてみたのですが、正しいでしょうか。

もし私の推測が間違っている場合は、その根拠を教えて頂けると助かります。

デバッグして確かめたのですが、なぜchの中身がは文字コード255となっているのかわかりません。
デバッグ画面

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

m.ts10806

2021/08/06 00:13

デバッグは現状の実装の調査のための手段でしかないのですけど、なぜデバッグが作用(悪さ)してるかのような書きぶりなのでしょうか。 書いたとおりにしか動きませんよ。デバッグは確認だけです。
退会済みユーザー

退会済みユーザー

2021/08/06 00:29

正しいのでしょうか?ではなく、動いた結果が全てです。 インデントすら付けない判り難いコードを書いてるから、自分でも把握できてないのでは。
maisumakun

2021/08/06 00:54

> y_waiwaiさんに過去にforの一週目のカッコの中身、すなわち(q = p; !(*q == '?' || *q == ':' || *q == 0); q++)のq++は働かないと聞きました。 当該発言があった場所を提示していただけませんか?(誤読・誤解・間違い等がある可能性も考えられます)
fana

2021/08/06 01:11

forがダメならwhileを使えばいいじゃない (forの文法的意味がわからん状態でデバッグとか言ってても何も進まないのは自明だから,まずはforと等価なwhileを書けるくらいになることからはじめよ,という意味)
m.ts10806

2021/08/06 02:04

>y_waiwaiさんに過去に 自分の勝手解釈を他人の責任とするとはいかがなものかと。
episteme

2021/08/06 02:35

> 過去にforの一週目のカッコの中身、すなわち(q = p; !(*q == '?' || *q == ':' || *q == 0); q++)のq++は働かないと聞きました。 それがホントか、デバッガで確認した?
Zuishin

2021/08/06 02:38

なぜもっと簡単なコードで確かめようとしないんだろう。 for (int i = 10; i < 20; i++) { printf("%d\n", i); }
fana

2021/08/06 03:01

そのコードの出力結果を見ることによって何かを確かめることができる者 (出力結果とコードとの対応関係を掴むことができる者) は,そもそもこのような質問をしないのではないかと推測します.
退会済みユーザー

退会済みユーザー

2021/08/06 03:15 編集

デバッグするなり、出力されたアセンブリコード確認するなりすればすぐ分かる事でしょう。何故しないの?
episteme

2021/08/06 03:36 編集

どれどれ... for (char* p = str; *p; ++p) { ++(*p); printf("%s\n", &(*p)); } 「for文の3番目はforのナカミが実行されてから実行される」もんです なので、そこの「プリント時点では」pは+1されてません ...とある。「一週目のみカッコの中身、q++は働かないと教わりました」は曲解だ。 # あなたのスキルが一向に向上しない一因は「こくご」にあるように思える。
Zuishin

2021/08/06 03:19

> は,そもそもこのような質問をしないのではないかと推測します. 出力を見れば、最初に i が 10 になっていることがわかります。 次に、最初の処理が終わってから i++ されていることがわかります。 そしていつまでループするかがわかります。 これでわからないなら質問しても無駄な気がしますが。 いや、もしかすると i ではなく太郎君の持っているミカンの数での説明を待っているのか。
carnage0216

2021/08/06 04:06 編集

episteme、よく読んだかな? 以下に書いたようにy_waiwaiさんが否定しないで、誤りを「その通りです」っていうから、それを信じただけなんですけどね。ここで否定してくれていればこんなややこしいことにはなっていないと思うんですが。国語力関係ありますか? 「なるほど、 一周目はforの中身が実行され文字コードの値が+1されてaがbとなり、 二周目からforの++pが働くためpは+1されて、forの中身が実行され文字コードの値が+1されるわけですね。 ちなみに、forループの一周目のみ++pが働かないというのは、C言語がそのように出来ているためでしょうか?」 「そういうことです。そういうふうに動作が決められているため、ですね これはCに限らず、他の言語でもそうなってますんで、覚えておくといいかと」 毎度毎度ですけど余計なことまで書いて場の空気を乱すならすっこんでて貰えますかね。正直害悪です。
m.ts10806

2021/08/06 04:13

基礎やれと何度言われても無視して感覚だけでやり続けて同じところ何年も回ってる人も大概害悪かと。 自身は何も乱してないという根拠はどこにありますか? 悪いのは理解しようとしない自分でしょう。
退会済みユーザー

退会済みユーザー

2021/08/06 05:14 編集

Webから拾ってきた情報をロクに検証すらせずに信用する方に問題がある。 てか、過去色々な人に問題を指摘されてきたにも関わらず、全く改善する兆しがないから、この人日本語読めないのかなと国語力指摘されてるんじゃないの。
fana

2021/08/06 04:46

> forループの一周目のみ++pが働かない の出所を見た感じ, この文の意味解釈には多分に文脈依存性があったものと推測する. 一見スムーズに会話が成立しているように見えるのだけども,実は両者が思っている意味は異なっていた ……っていうだけの話なんじゃないかな. そして,それと同様のことが,今現在,この質問でも生じているかもしれない. > forループの一周目のみ++pが働かない っていう文がどういう意味のことを言っているのか?という解釈が,書き手と読み手の間で異なっているかもしれない.
episteme

2021/08/06 05:01 編集

> episteme、よく読んだかな? よく読みましたとも。 それにアナタいまデバッガ使って動作を確認してるんじゃなかったっけ? その過程で「~と聞きました」の真偽が明らかになったはずでは? 何のためにデバッガ使ってるん? # 場の空気乱してる? 乱れてませんけど。
Zuishin

2021/08/06 06:08

> なぜchの中身がは文字コード255となっているのかわかりません。 未初期化だから、以上の説明がいるのか?
episteme

2021/08/06 06:20 編集

↑追試してみた。やはり ch は '?', ':', '\0' 以外にはならない。 # int ch; された直後は(不定なので)どんな値であっても文句言えないわけだが。 ...ひょっとして Release-build したやつをデバッガに食わせてはいないか?
int32_t

2021/08/06 06:27

for (A; B; C) { D } とあったとき、D の前にCは実行されない、という意味でしょう。この質問のコードの場合 D がありませんし、ほぼ関係ない話に見えます。 質問者さん、「1周目」とか「2周目」とかに言及するときは、外側のループの話なのか内側のループの話なのか気を付けてください。
carnage0216

2021/08/06 06:34 編集

未初期化だとどんな変数の中身もコード255と出るのですか? >>質問者さん、「1周目」とか「2周目」とかに言及するときは、外側のループの話なのか内側のループの話なのか気を付けてください。 内側のループです。
Bull

2021/08/06 07:16

episteme さん > ...ひょっとして Release-build したやつをデバッガに食わせてはいないか? その可能性が高いです。 デバッガの画像を見ると 'ucrtbase.dll' や 'vcruntime140.dll' が読込まれていますが、 Debug-build すれば、'ucrtbased.dll' や 'vcruntime140d.dll' が読込まれるはずです。
退会済みユーザー

退会済みユーザー

2021/08/06 07:22 編集

というか、ツールバーのソリューション構成がReleaseになってますね。
episteme

2021/08/06 07:44

> 未初期化だとどんな変数の中身もコード255と出るのですか? "不定"なんだから何が入っていようがその理由を問うのはナンセンス。(やっぱ「こくご」が...)
carnage0216

2021/08/06 08:19

ナンセンスで結構。 >>(やっぱ「こくご」が...) 慎重ゆえに確認のために聞いただけなのに、それすらも国語力なのか。 小うるさいじぃさんだなぁ。
maisumakun

2021/08/06 08:22

> ナンセンスで結構。 「意味がない」ということにも重要な意味があります(よほどの理由がない限り、未定義の領域に突っ込むようなコードは書いてはいけません)。
Bull

2021/08/06 08:23

carnage0216 さん Release-build では正確にデバッグできません。 デバッグするのであれば、Debug-build した方がいいです。
episteme

2021/08/06 08:38

> 慎重ゆえに確認のために聞いただけなのに、それすらも国語力なのか。 不定であることの確認だというなら「ではこの255には意味がないんですね? 偶々255なんですね」と確認すんじゃね? それとも何を確認したかったん?
carnage0216

2021/08/06 09:07 編集

Bullさん、ありがとうございます。 「ではこの255には意味がないんですね? 偶々255なんですね」←エピさんも確認してるみたいな文章じゃんw 国語力関係ないじゃん。 国語力マウント取れてよかったね!おじいちゃん! 国語マウントとりたいだけのエピカス国語力おじさんは帰ってどうぞ。
maisumakun

2021/08/06 09:16 編集

> 国語力関係ないじゃん。 carnage0216さんのほうが、相手の文章もろくに読まずに反射的に返信していることがよくわかりました(「確認するんだったらこのようになるのでは?」という提示に対して「確認してるみたいな文章じゃん」と突っ込むのは、何がしたいのかわからないです)。
carnage0216

2021/08/06 09:26

提示してきたのはわかってますよ。 私もエピカスのどっちも「特におかしい点のない確認のための文章」だから国語力関係ないよねっていっただけなんですけど。そんなに難しい話はしていないですよ。 話の論点の理解が曖昧なのに無理に横入りしなくても大丈夫です。というかややこしくなるんでやめて下さい。w >> 何がしたいのかわからないです わからなくていいんじゃないすか。
Zuishin

2021/08/06 09:52 編集

特におかしくないと信じてるあたりが国語力のなさを示しているが、難しい話なので理解できないだろう。 そんな難しいことより、さっさとビルド構成を変えて試してみたらいい。 簡単なことだから。
carnage0216

2021/08/06 10:34

国語力関係ないのに国語力マウントおじさんが多いなぁw 老害化してしまいますよ?既にしてるけど。w エピカス並みにしつこくて説明が下手な人がいるけど。マゾ系の方? なら気持ち悪いから帰って欲しいなw
Zuishin

2021/08/06 10:35

お前に理解できるよう説明できる人の方が少ないことにまだ気づかないのか? 帰るならお前が知恵袋に帰れ。
Zuishin

2021/08/06 10:39

そもそも普通の国語力があれば for くらい一人で勉強して数分で理解できるもんだろう。 なぜ自分に国語力があると思った? 国語の成績は良かったのか? 全国模試で偏差値 50 あったか?
carnage0216

2021/08/06 10:53 編集

なんか勝手にマジギレしてて草。 図星を突かれて国語力マウントを取りまくるのは大草ですわ。 血圧上がってしまい健康に良くないですよ! まぁ、プログラミングのような繊細な物を人に教えるのは難しいですからね。 特にエピカスの解説は壊滅的にわかりにくい。それに粘着質に現れてキモいから5○7で○んでくれないかなー。
Zuishin

2021/08/06 10:58

国語力どうした? 普通の人が普通に読めるページが読めないとか言わないよな? ほら、余計なことはいいから読んで自己解決して帰れ。
Zuishin

2021/08/06 11:01

なんならここを読んでもいいぞ。さっきのは一般向けだが、こっちは技術者向けだ。と言っても難しいことは何も書いてないから普通の国語力があれば中学生でも余裕で読める。 https://docs.microsoft.com/ja-jp/cpp/cpp/for-statement-cpp?view=msvc-160 中学生以上の国語力はあるんだろ? じゃあ解決だな。帰れよ。
episteme

2021/08/07 00:33

ともあれ現状ではデバッガを正しく使えていないようだから、 Debug-build に構成変更したうえでデバッガ動かし、質問を修正してくださいな。
guest

回答5

0

ベストアンサー

for文を for (A; B; C) D とします。
A は初期化、B は判定、C は更新、D は処理です。

B の判定が 3回ループ続行 で、4回目にループ終了になるとすれば、
次のように実行されます。

A
B D C (1周目)
B D C (2周目)
B D C (3周目)
B

1周目は C が実行されないのではなく、ループの最後で実行されます。

ソースに書かれているのが、A B C D の順なのに、B の次が D だから
1周目は C が実行されないと思っているのでしょうか?

ch の値が気になるのなら、ch = *q; の行にブレークポイントを置いて、
この行の実行前の ch の値を見て、ステップ実行で
ch = *q; 実行後の ch の値がどう変わるかを見ましょう。
ch = *q; は3回通るので、その全部の値を見てください。

コメントをお願いします。

追記

疑問があります。なぜforループの二周目以降のデバッグでのstr[]の中身はstr == NULLであるのに、一週目のみstr[]の中身はstr == NULL ? "(NULL)": strであるかについてです。

質問の最初の部分について回答します。
Visual Studio で変数の値を見ていますよね。

変数strの値として、その変数のアドレスと、
そこから'\0'までの文字列が表示されています。

str の前の「右向き△」をクリックして「下向き▽」にしてください。
str[0]~str[27] がすべて表示されます。

表示ウィンドウが画面の下にあって全部見えないなら、
その表示ウィンドウをドラッグして右側に移動して縦に長くしてください。

str[0] が 115 's'
str[12] が 63 '?'
str[22] が 58 ':'
str[27] が 0 '\0'

外側の for(;;) のループの 1周目で *q = 0; を実行する前は
str[27] が '\0' なので、str は文字列全体が表示されます。
*q = 0; を実行すると、str[12] が 0 '\0' になり、
変数 str の文字列表示は "str == NULL" だけになります。
str[0] から str[12] までの文字列を表示しているからです。

2周目で *q = 0: を実行すると、str[22] が 0 '\0' になりますが、
変数 str の文字列表示は "str == NULL" のままです。
str[0] から str[12] までの文字列を表示しているからです。

3周目で *q = 0: を実行すると、元から 0 の str[27] が 0 のままで、
変数 str の文字列表示は "str == NULL" のままです。
str[0] から str[12] までの文字列を表示しているからです。

なお、printf("|%s|\n", p); で表示しているのは、
str の中の p から q までの部分文字列です。
1周目は str[0]~str[12] の "str == NULL"
2周目は str[13]~str[22] の " "(NULL)""
3周目は str[23]~str[27] の " str"

以上のことを Visual Studio で試してみて確認し、
説明が理解できたかどうかをコメントしてください。

投稿2021/08/06 11:52

編集2021/08/07 07:27
kazuma-s

総合スコア8224

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

carnage0216

2021/08/08 01:23

chの値は文字列に含まれる?'、':'、 0を通るたびに数値が変化していました。 一回目は63、二回目は58、最後は0です。それぞれ'?'、':'、 0を表しているとわかりました。
kazuma-s

2021/08/08 02:43 編集

ch が 255 になるというのはどうなったんですか? また、str は見ましたか? 説明が理解できたかどうかのコメントもお願いします。
kazuma-s

2021/08/10 03:13

> chの値は文字列に含まれる?'、':'、 0を通るたびに数値が変化していました。 > 一回目は63、二回目は58、最後は0です。それぞれ'?'、':'、 0を表しているとわかりました。 63になる前は何でしたか? それが 255 ですか?
carnage0216

2021/08/10 09:32

63になる前は0だと思います。
kazuma-s

2021/08/10 10:37

「だと思う」ではなく、デバッガ(Visual Studio)で実際に見た値を書いてください。 いつ 255 になるんですか? src[0]~src[27]は常に全部見ていますか? for文で 1周目が特別で、2周目からとは違うという思い込みは解消されましたか? A B D (1周目は特別で C を実行しない) B C D (2周目) B C D (3周目) B だと思っていたんですよね。
guest

0

for (q = p; !(*q == '?' || *q == ':' || *q == 0); q++);

ここで ; で区切られて書かれている3つの式がどんな順序でどのように使われるのか?
っていう基本中の基本をまず理解すべき.

これを知らなければ,そのコードを読めないし書けない.
当然,そんな状態でデバッグ作業なんてできるわけがない.

この for によるループを while を用いて書けば,こうだ.

C

1//最初に,変数qにpの値を代入する 2q = p; 3// qが指す先が { '?', ':', 0 } のいずれでもない間ループする 4while( !(*q == '?' || *q == ':' || *q == 0) ) 5{ 6 //qの値を更新 7 q++; 8}

あるいはこのように書いても同じ.

C

1//最初に,変数qにpの値を代入する 2q = p; 3 4while( 1 ) 5{ 6 // qが指す先が { '?', ':', 0 } のいずれかであればループを抜ける 7 if( (*q == '?' || *q == ':' || *q == 0) ) 8 { break; } 9 10 //qの値を更新 11 q++; 12}

以上から,

  • q++ がいつ実行されるのか?
  • それが一度も実行されない場合,qの値はどうなってるのか?

等が把握できると思う.
(もちろん「このコードを読めれば」,であるが)

このような基礎すぎる事柄を把握してさえいれば

q++が働かなったためにqには0や値すらも入らないため…

とか言い出すことは決して無い.

もちろん誰だって最初は物を知らない時期があるのだから「聞くは一時の恥」ということはあり得るのだが,
であれば「一時」で済ませるべきではなかろうか.

投稿2021/08/06 02:47

編集2021/08/06 02:49
fana

総合スコア11656

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

fana

2021/08/06 03:06

…というわけで, (既に何度となく言われただろうと思うけども)基礎文法を学ぶことから始めるべきと思う. 何が書いてあるのかが全くわからないコードを相手にしてても仕方ない. そのコードのことは今すぐ忘れて,そのコードと同等の処理を達成するコードを自分で書けるだけの力を付けるべき. 他人が書いたコードを読むという行為は,自分で同等のコードを書くよりもずっと難易度が高い行為だ. 難易度が低い側からやるべき.
fana

2021/08/06 05:09

唐突な自分語り. 大昔に大学のC言語の講義のTAとかをやってきた経験によると, for の 「 ; で区切られて書かれている3つの式がどんな順序でどのように使われるのか?」 を理解していない状況(ぼんやりと捉えている,というか)というのはわりとよくある様子. そのような相手には while に置き換えてみることを勧めてきた. とりあえず while を用いて書いてみて,それを for で書いたらどうなるか?をやってみるのである. 今回も通用すればよいが.
guest

0

なぜforループの二周目以降のデバッグでのstr[]の中身はstr == NULLであるのに、一週目のみstr[]の中身はstr == NULL ? "(NULL)": strであるか

初期状態:

str[] = "str == NULL ? "(NULL)": str"

char *p, *q; p = str; // p は str(の先頭)を指す

■ 一週目:

for (q = p; !(*q == '?' || *q == ':' || *q == 0); q++);

これにより、q は'?',':','\0' のいずれかを指す位置となる。
つまり qは "str == NULL ? "(NULL)": str" の'?'を指す。

ch = *q;

***q = 0**;

これにより、q の指す '?' が '\0' に書き換えられる。

したがって str[] = "str == NULL \0 "(NULL)": str" となる。

これ以降すなわち二週目以降、文字列は'\0'で終端されるため
printf("%s", str) で得られる出力は "str == NULL "

投稿2021/08/06 02:19

編集2021/08/07 00:27
episteme

総合スコア16614

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

episteme

2021/08/06 11:44

さて、これのどこが低評価?
guest

0

qには0や値すらも入らないため

いえ、forの先頭のq=pで値は初期化されます。

投稿2021/08/06 00:55

maisumakun

総合スコア145183

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

maisumakun

2021/08/06 01:04

> 考えてみたのですが なぜそれを確認しようとしないのでしょうか?
guest

0

「デバッグでのstr[]の中身」というのが何を指しているのか不明瞭ですが、

・外側のループの1周目は、*q = 0; が実行されるまで str[] には変更がないので、初期値のままです。
・それ以降は、? の部分が 0 に書き換えられているので、"str == NULL " に見えます。

q++が働かなったためにqには0や値すらも入らないためp = q + 1;が動かず、

「値すら入らない」なんてことはないです。q++が動かなければ値が変わらないだけです。また、このコードでは内側のループでq++が実行されないケースはないように見えます。

投稿2021/08/06 00:30

編集2021/08/06 00:32
int32_t

総合スコア20872

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

carnage0216

2021/08/06 00:51

q++が動かなければ値が変わらないだけです。 との事ですが、その場合は q=0で、p=q+1はp=1という事でしょうか?
int32_t

2021/08/06 01:36 編集

> q=0で、p=q+1はp=1という事でしょうか? もし内側のループで q が 0 で初期化されて、内側のループが1度も回らなければ、そうです。 実際は、q が 0 で初期化されることはありませんし、回答に書いたようにこのコードのstr[]で内側のループが1度も回らないことは起きないと思いますが。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問