すみません。昨日、某巨大掲示板で質問したのですが、アクセス規制喰らったので。。ここで聞かせてください。C言語を色々と実験中の者です。
int a[]={1,2,3,0}, *p=a-1;
for(;*p++;){ // 何らかの処理 }
とすると、*pが終了条件に当てはまってないか確認されてからp++されるということをしりました。
これは printf("%d", *p++); の一文がまず*pの値が(インクリメントする前の値が)%dに代入され表示されて、そのあとにp++でインクリメントされるのと似ています。というか、動作は一緒です。これは、後置インクリメント演算子は、その一文が評価されてから、インクリメントされるということですが。
そうすると前述のfor(;*p++;)のp++;の部分も文と考えれらるような気がするのですが。。;で区切られていますし、やはり文法的に言うと文になるのでしょうか?
マルチになるのかもしれませんが、よろしくお願いします。某巨大掲示板をプロバイダ規制喰らったので。。
No.1
- 回答日時:
文法的に言うと文です。
あってますよ。質問とは別のところで気になるところがふたつ。
1.「*pが終了条件に当てはまってないか~」ではなくて、真/偽の判定です。
2.「*p=a-1;」のあとすぐfor文の中で*pを評価してますが、これは環境によってはクラッシュしますし、真/偽の判定も意図した通りにはなりません。
どうもありがとうございます。
なんか、Cは細かいことが結構厳しくとり決まっていますね。私はJavaやらPHPをやっていたのですが、Cの厳しい文法の取り決めが新鮮でもあり混乱の元でもあります。。
ご指摘いただきました、1,2についての問題点ですが、2の場合はかなりあぶないんですね。なにぶん、本とネットしか情報収集手段がないので、そこまで書いてある情報にたどり着けませんでした。私は、サンデープログラマなので・・・
有益な情報をありがとうございました。2については、気をつけます。
ありがとうございました。
No.2ベストアンサー
- 回答日時:
結論から言うと、文ではなく式です。
質問の中には色々間違った解釈があるのですけれど、まず*p++の解釈を覚えてください。後置インクリメント演算子は「対象の左辺値(ここでは変数p)の値がインクリメントされ(+1した値に置き換えられる)、その値はインクリメント前の値」という演算子です。
ですから、例えばprintf()の例で、まず*pの値が~というのは違っていて「pの値が+1される。(p++)の値は+1されるまえのpの値。*(p++)の値は+1されるまえのpの指しているアドレスの値。それが%dに対応して(文字列化されて)表示される」です。決して「一文が評価されてからインクリメント」などという「文」を単位とした実行順序の解釈と式の評価とは関係ありません。
文の解釈と(一つの文の中の)式の評価順序(代入順序も然り)は関係ありません。
もう一度、もとの話に戻って説明すると
>*pが終了条件に当てはまってないか確認されてからp++される
というのは違っていて、
1) pのインクリメント
2) p(インクリメント前)の指すメモリからの値の取り出し
3) 2で取り出した値が0かどうか(終了条件)を判断
という順序です。インクリメントのタイミングは文の終わりとかそういうタイミングとは関係なく、式の評価の中で行われるものです。
ただし、コンパイラがどういう順序で実行するようにコードを出力するかはまた別の問題です。仮に順序を変えたとしても上のような解釈に影響を与えない範囲で(例えばpの値が参照されるまでインクリメント値の代入を遅らせるコードを出力するとか)出力コードの順序を変更することはあるでしょう。
どうもありがとうございます。
とてもよく、インクリメント演算子がよくわかりました。+1されてるんだけど、表示される値は+1される前の値なんですね。こんなこと、どの書籍にものっていないので、教えていただきとても助かります。
あと、for文の終了条件の順序もおかげさまで完全に理解できました。for文とか本で言う一通りの使い方はわかりましても、このような完璧な動作内容まで理解できるととても感動しますね。
また、コンパイラによって出力される機械語が違うというのは2chでよくみるんですが、自分には理解できなかったのですが、一番最後の詳しい解説により理解できました。ん~、なるほど各メーカーのCコンパイラによって規約にそぐわない範囲で出力コードが違うという事なんですね。
しかし、とても勉強になりました。私など、独習Cとネットくらいしか情報手段がないので。。
本当に参考になりました。正直なところ、ちょっと感動を覚えています。Cは細かいところが真のおもしろさとも思えました。とてもご丁寧な回答ありがとうございました。
No.3
- 回答日時:
ANo.2で回答したものです。
少し補足します。
ある記述が(C言語の文法に照らし合わせて)「文」であるか「式」であるかというのはC言語の文法を調べれば正しい意味で判断することができます。ですので、できれば実験などといわずにそういう規約(規格)を参照するのがよいと思います。
ここでは質問の場合について、一例を示します。
C言語には複文というものがあります。いくつかの文をとりまとめたもので、一つの文を書けるところに書くことができます。例えばif文の書式(文法)は
if (式) 文
ですが、条件式が成り立つとき(値が真であるとき)に複数の文を実行したいことはあります。そこに複文を使います。こんな感じです。
if (a[i] > x) {
x = a[i];
index_max = i;
}
この{ ... }の部分が複文です。ifの条件成立時に実行する文は一つだけ書くことができます(上記のif構文)けれど、そこに複数の文を書くために一つの複文にまとめています。
上に書いたように「一つの文を書けるところには複文を書くこと」ができます。では、次の記述は許されるでしょうか。
for (i=0; { i++; check(); i < 100; }; ) ...
for文の構文は for (式; 式; 式) 文 であって、()内の";"は単に式の区切りです。式につけて文を構成するための";"とは違うものです。
2度目の回答ありがとうございます。
なるほど。式と文の明確な違いもやはりしっかり理解しないといけないですね。英文法とかだとわりあいアバウトでも会話が通じますが。。試験は通らないですもんね。
文法というのがここまで厳しいか?というのが、ちょっと意外であり、正直な感想です。私はサンデープログラマなのであれなんですが、仕事なんかだと厳しくなきゃやってられなさそうですね!もともとWinAPIをやっているためにCを細かく知ろうとしたんですが、なんかCの単純だけど、機械語に近い面白さを知りまして。。もっぱら、こっちやってます。
とにかく、これからは、規約を調べてみてみようとおもいます。
2度にわたる、ご丁寧な解説ありがとうございました。とても、勉強になりました。
No.4
- 回答日時:
Cの場合、第1節は「式」または「宣言」です。
したがって「文」ではありません。ちなみに、C++では第1節は「文」になります。ただし、一般的な文ではないので、ここに記述できる内容は限られています。具体的には、forの第1節に、for文やgoto文やreturn文などは記述できませんし、複合文も記述できません。記述できるのは、式文と単純宣言だけです。
また、第2節には、
for (int i = 0; char c = str[i]; i++)
のように宣言を含めることができますが、これは文扱いではありません。宣言できるのもスカラ型に限られます。
なるほど、式、文以外に宣言という手もあるのですね。
そういわれてみるとそうだなあとおもいます。Javaをやっていたこと無意識にfor(int i=0;~;~)とやってましたが、あれは文なんですね。CとC++での定義の違いがこんなところにもあるんだなあと感心しております。
例で紹介いただいたfor文の第2節は宣言になるんですね。C++も興味があるので、近いうちに色々調べてみようとおもいます。
私は元来単純な計算が好きだったので、Cの素朴なプログラムに工夫をするのが今面白いです。いい頭の体操にもなりますし。
どうも今回はありがとうございました。感謝します。
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
似たような質問が見つかりました
- C言語・C++・C# C言語のエラーについて 2 2022/07/11 13:56
- C言語・C++・C# c言語 プログラムのエラー 1 2023/02/11 20:31
- JavaScript Javascriptが機能せず原因が分からないので教えて頂きたいです 3 2023/06/04 14:50
- 英語 「名詞+for...to不定詞句」で「for以降」が完全な文となる場合の名詞との関係について 4 2023/04/26 09:45
- Java javaでのプログラム(配列)について質問です. 2 2022/10/14 22:27
- C言語・C++・C# 至急教えてください。プログラミングの問題です。 最初に正の整数nの入力を受け付け、次に分数の分子と分 1 2022/07/19 17:03
- C言語・C++・C# 至急お願いします。プログラミングの問題です。 最初に正の整数nの入力を受け付け、次に分数の分子と分母 3 2022/07/19 17:09
- C言語・C++・C# 至急教えてください。プログラミングの問題です。 malloc関数を使ってください!お願いします! 最 1 2022/07/21 09:28
- 哲学 日本語のあたらしい文法を考えよう。 6 2022/06/25 17:41
- 哲学 日本語は 言語類型として あたかも始原のごとくである 3 2022/05/29 04:41
関連するカテゴリからQ&Aを探す
おすすめ情報
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
c言語
-
H8マイコン C言語でのプロ...
-
繰り返し1行~28行までを順順に...
-
エクセルで特定の列が0表示の場...
-
配列数式の解除
-
Excel・Word リサーチ機能を無...
-
特定のPCだけ動作しないVBAマク...
-
マクロで"#N/A"のエラー行を削...
-
EXCELのVBAでRange("A1:C4")を...
-
ExcelVBAでPDFを閉じるソース
-
2つのマクロでチェックボックス...
-
エクセルのマクロについて教え...
-
VBA【dictionary勉強中ですが・...
-
配列でデータが入っている要素...
-
教えて下さい
-
TERA TERMを隠す方法
-
2つ以上の変数を比較して最大数...
-
String""から型'Double'への変...
-
Excel マクロ VBA プロシー...
-
UserForm1.Showでエラーになり...
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
c言語
-
繰り返し1行~28行までを順順に...
-
!(否定)演算子について
-
H8マイコン C言語でのプロ...
-
MATLABにおける行の挿入方法
-
五目並べ
-
パイソンのプログラミングにつ...
-
if文について教えてください
-
C言語で余りがマイナスになる場合
-
Scilabで行列をグラフ化したい...
-
フォートランで行列の計算
-
Numpyのrandom.multivariate_no...
-
アセンブラの間接アドレッシング
-
C言語で行列表現
-
収束計算
-
ダイナミックプログラミング
-
MATLABのfor文の使い方について
-
OPENCVを使ったエピポーラ幾何...
-
cのプログラミングで虚数を含...
-
≪C言語≫キー入力の判断について
おすすめ情報