アプリ版:「スタンプのみでお礼する」機能のリリースについて

すみません。昨日、某巨大掲示板で質問したのですが、アクセス規制喰らったので。。ここで聞かせてください。C言語を色々と実験中の者です。

int a[]={1,2,3,0}, *p=a-1;
for(;*p++;){ // 何らかの処理 }
とすると、*pが終了条件に当てはまってないか確認されてからp++されるということをしりました。

これは printf("%d", *p++); の一文がまず*pの値が(インクリメントする前の値が)%dに代入され表示されて、そのあとにp++でインクリメントされるのと似ています。というか、動作は一緒です。これは、後置インクリメント演算子は、その一文が評価されてから、インクリメントされるということですが。

そうすると前述のfor(;*p++;)のp++;の部分も文と考えれらるような気がするのですが。。;で区切られていますし、やはり文法的に言うと文になるのでしょうか?

マルチになるのかもしれませんが、よろしくお願いします。某巨大掲示板をプロバイダ規制喰らったので。。

A 回答 (4件)

結論から言うと、文ではなく式です。



質問の中には色々間違った解釈があるのですけれど、まず*p++の解釈を覚えてください。後置インクリメント演算子は「対象の左辺値(ここでは変数p)の値がインクリメントされ(+1した値に置き換えられる)、その値はインクリメント前の値」という演算子です。

ですから、例えばprintf()の例で、まず*pの値が~というのは違っていて「pの値が+1される。(p++)の値は+1されるまえのpの値。*(p++)の値は+1されるまえのpの指しているアドレスの値。それが%dに対応して(文字列化されて)表示される」です。決して「一文が評価されてからインクリメント」などという「文」を単位とした実行順序の解釈と式の評価とは関係ありません。

文の解釈と(一つの文の中の)式の評価順序(代入順序も然り)は関係ありません。

もう一度、もとの話に戻って説明すると
>*pが終了条件に当てはまってないか確認されてからp++される
というのは違っていて、
1) pのインクリメント
2) p(インクリメント前)の指すメモリからの値の取り出し
3) 2で取り出した値が0かどうか(終了条件)を判断
という順序です。インクリメントのタイミングは文の終わりとかそういうタイミングとは関係なく、式の評価の中で行われるものです。


ただし、コンパイラがどういう順序で実行するようにコードを出力するかはまた別の問題です。仮に順序を変えたとしても上のような解釈に影響を与えない範囲で(例えばpの値が参照されるまでインクリメント値の代入を遅らせるコードを出力するとか)出力コードの順序を変更することはあるでしょう。
    • good
    • 0
この回答へのお礼

どうもありがとうございます。

とてもよく、インクリメント演算子がよくわかりました。+1されてるんだけど、表示される値は+1される前の値なんですね。こんなこと、どの書籍にものっていないので、教えていただきとても助かります。

あと、for文の終了条件の順序もおかげさまで完全に理解できました。for文とか本で言う一通りの使い方はわかりましても、このような完璧な動作内容まで理解できるととても感動しますね。

また、コンパイラによって出力される機械語が違うというのは2chでよくみるんですが、自分には理解できなかったのですが、一番最後の詳しい解説により理解できました。ん~、なるほど各メーカーのCコンパイラによって規約にそぐわない範囲で出力コードが違うという事なんですね。

しかし、とても勉強になりました。私など、独習Cとネットくらいしか情報手段がないので。。

本当に参考になりました。正直なところ、ちょっと感動を覚えています。Cは細かいところが真のおもしろさとも思えました。とてもご丁寧な回答ありがとうございました。

お礼日時:2008/06/02 13:20

Cの場合、第1節は「式」または「宣言」です。

したがって「文」ではありません。

ちなみに、C++では第1節は「文」になります。ただし、一般的な文ではないので、ここに記述できる内容は限られています。具体的には、forの第1節に、for文やgoto文やreturn文などは記述できませんし、複合文も記述できません。記述できるのは、式文と単純宣言だけです。
また、第2節には、

for (int i = 0; char c = str[i]; i++)

のように宣言を含めることができますが、これは文扱いではありません。宣言できるのもスカラ型に限られます。
    • good
    • 0
この回答へのお礼

なるほど、式、文以外に宣言という手もあるのですね。

そういわれてみるとそうだなあとおもいます。Javaをやっていたこと無意識にfor(int i=0;~;~)とやってましたが、あれは文なんですね。CとC++での定義の違いがこんなところにもあるんだなあと感心しております。

例で紹介いただいたfor文の第2節は宣言になるんですね。C++も興味があるので、近いうちに色々調べてみようとおもいます。

私は元来単純な計算が好きだったので、Cの素朴なプログラムに工夫をするのが今面白いです。いい頭の体操にもなりますし。

どうも今回はありがとうございました。感謝します。

お礼日時:2008/06/02 13:35

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 (式; 式; 式) 文 であって、()内の";"は単に式の区切りです。式につけて文を構成するための";"とは違うものです。
    • good
    • 0
この回答へのお礼

2度目の回答ありがとうございます。

なるほど。式と文の明確な違いもやはりしっかり理解しないといけないですね。英文法とかだとわりあいアバウトでも会話が通じますが。。試験は通らないですもんね。
文法というのがここまで厳しいか?というのが、ちょっと意外であり、正直な感想です。私はサンデープログラマなのであれなんですが、仕事なんかだと厳しくなきゃやってられなさそうですね!もともとWinAPIをやっているためにCを細かく知ろうとしたんですが、なんかCの単純だけど、機械語に近い面白さを知りまして。。もっぱら、こっちやってます。

とにかく、これからは、規約を調べてみてみようとおもいます。

2度にわたる、ご丁寧な解説ありがとうございました。とても、勉強になりました。

お礼日時:2008/06/02 13:27

文法的に言うと文です。

あってますよ。

質問とは別のところで気になるところがふたつ。

1.「*pが終了条件に当てはまってないか~」ではなくて、真/偽の判定です。

2.「*p=a-1;」のあとすぐfor文の中で*pを評価してますが、これは環境によってはクラッシュしますし、真/偽の判定も意図した通りにはなりません。
    • good
    • 0
この回答へのお礼

どうもありがとうございます。

なんか、Cは細かいことが結構厳しくとり決まっていますね。私はJavaやらPHPをやっていたのですが、Cの厳しい文法の取り決めが新鮮でもあり混乱の元でもあります。。

ご指摘いただきました、1,2についての問題点ですが、2の場合はかなりあぶないんですね。なにぶん、本とネットしか情報収集手段がないので、そこまで書いてある情報にたどり着けませんでした。私は、サンデープログラマなので・・・

有益な情報をありがとうございました。2については、気をつけます。
ありがとうございました。

お礼日時:2008/06/02 13:04

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