掲示板利用宣言

 次のフォームをすべてチェックしてからご利用ください。

 私は

 題名と投稿者名は具体的に書きます。
 課題の丸投げはしません。
 ソースの添付は「HTML変換ツール」で字下げします。
 返信の引用は最小限にします。
 環境(OSとコンパイラ)や症状は具体的に詳しく書きます。
 返信の付いた投稿は削除しません。
 マルチポスト(多重投稿)はしません。

掲示板2

管理者用メニュー    ツリーに戻る    携帯用URL    ホームページ    ログ    タグ一覧

No.25968

ソースの意味
投稿者---milk(2006/02/03 14:22:22)


#include <stdio.h>
int main()
{
    int x=1;
    do{
        x*=(++x);
    }
    while(x<10);
 printf("%d\n", x);
}


このソースを実行すると42って出てきます。x*=(++x)って
x=x(++x)っていう意味ですよね。
xが10になるまで繰り返すっていうプログラムだと思うんですけど・・・
何で実行結果が42になるか教えて下さい。


この投稿にコメントする

削除パスワード

発言に関する情報 題名 投稿番号 投稿者名 投稿日時
<子記事> Re:ソースの意味 25969 kz3 2006/02/03 14:38:19
<子記事> Re:ソースの意味 25970 YuO 2006/02/03 14:39:02
<子記事> Re:ソースの意味 25971 Blue 2006/02/03 14:41:12


No.25969

Re:ソースの意味
投稿者---kz3(2006/02/03 14:38:19)



#include <stdio.h> int main() { int x=1; do{ x*=(++x); } while(x<10); printf("%d\n", x); }
>x=x(++x)っていう意味ですよね。 >xが10になるまで繰り返すっていうプログラムだと思うんですけど・・・ >何で実行結果が42になるか教えて下さい。 「xが10になるまで繰り返す」ではありません。 「xが10未満の間繰り返す」です。 インクリメント演算子の前置形、後置形の理解不足です。 前置形はインクリメント演算が行われてから式が評価されます。 後置形は式が評価された後にインクリメント演算が行われます。 という事を踏まえればxの値がループに入ってから 2 > 6 > 42 と移り変わることは容易に想像つくでしょう。




この投稿にコメントする

削除パスワード

No.25970

Re:ソースの意味
投稿者---YuO(2006/02/03 14:39:02)


        x*=(++x);

このソースを実行すると42って出てきます。x*=(++x)って
x=x(++x)っていう意味ですよね。



そもそも,このソースは引用部分が未定義動作(副作用完了点間に同一オブジェクトへの副作用が複数回存在する)なので,結果として何が出てくるかは予想できません。



この投稿にコメントする

削除パスワード

No.25973

Re:ソースの意味
投稿者---kz3(2006/02/03 15:03:53)


私は何の疑いも持たずに
1 * 2
2 * 3
6 * 7
と式を解釈してしまいましたが、これは未定義の動作だったのですね。
勉強になりました。

参考:C FAQ 3章.式


この投稿にコメントする

削除パスワード

No.25975

Re:ソースの意味
投稿者---milk(2006/02/03 15:13:28)


未定義動作とは何でしょうか?教えて下さい。
lcc-win32使ってるんですが42しかでてきませんでしたが。

演算子について理解できました!!




この投稿にコメントする

削除パスワード

No.25976

Re:ソースの意味
投稿者---nop(2006/02/03 15:26:59)


>未定義動作とは何でしょうか?

規格として定義されていない動作の事です。



この投稿にコメントする

削除パスワード

No.25977

Re:ソースの意味
投稿者---milk(2006/02/03 15:45:38)


>>未定義動作とは何でしょうか?
>
>規格として定義されていない動作の事です。

日本語の意味はわかるんですけど、何でこのソースが未定義なんでしょうか。



この投稿にコメントする

削除パスワード

No.25978

Re:ソースの意味
投稿者---RiSK(2006/02/03 15:53:43)


>日本語の意味はわかるんですけど、何でこのソースが未定義なんでしょうか。

すでにYuOさんが説明しています。
C言語の規格でそう決められている,
としか答えられないです。
処理系が各々最適化出来るように未定義にしているの。


この投稿にコメントする

削除パスワード

No.25990

Re:ソースの意味
投稿者---Ban(2006/02/05 00:15:27)


> 日本語の意味はわかるんですけど、何でこのソースが未定義なんでしょうか。

この場合の未定義動作ってのは、読んだ通りの日本語ではなくて、
C 言語で規定してる「未定義動作(undefined behavior)」という「用語」です。
CはC99しか手元にないですが、この場合 3.4.3 で定義されてます。

ISO/IEC 9899:1999

undefined behavior

behavior, upon use of a nonportable or erroneous program construct or of erroneous data, for which this International Standard imposes no requirements


簡単に言えば「結果を保証してないからこういうソースは書かないでね」ってのが「未定義動作」です。
# コンパイラ側からみれば、無視したり、適当にあしらってもかまわない。

そして、規格書の Annex J に Portability issues として、
undefined behavior (やら unspecified behavior やら)が列挙されてます。(C99の場合)
で、先のソースは以下の条件に抵触するため、未定義動作になります。

ISO/IEC 9899:1999

Annex J (informative)

J.2 Undefined behavior

Between two sequence points, an object is modified more than once, or is modified and the prior value is read other than to determine the value to be stored (6.5).





この投稿にコメントする

削除パスワード

No.25991

Re:ソースの意味
投稿者---Ban(2006/02/05 00:27:17)


YuO サンの書かれている
「副作用完了点間に同一オブジェクトへの副作用が複数回存在する」というのが、
「Between two sequence points, an object is modified more than once」です。
JISX3010(上記規格書の日本語訳版)だとこうなってるのかと思います。


この投稿にコメントする

削除パスワード

No.25971

Re:ソースの意味
投稿者---Blue(2006/02/03 14:41:12)


環境が不明ですが、

x = 1  x *= ( ++x ) ---> 1 * 2 = 2
x = 2  x *= ( ++x ) ---> 2 * 3 = 6
x = 6  x *= ( ++x ) ---> 6 * 7 = 42

ですかね?

ただ、私のコンパラ(Windows XP, VC++ 6.0 Sp6 Enter)では

x = 1  x *= ( ++x ) ---> 2 * 2 = 4
x = 4  x *= ( ++x ) ---> 5 * 5 = 25

ですね。(VC6はダメダメらしいからなんともいえない。。。)
# 他のコンパイラは今手元にないからワカラナイ。

なんかコンパイラの処理の仕方(順番とか?)が関連して1行に書いてはいけないっぽい。



この投稿にコメントする

削除パスワード

No.25986

Re:ソースの意味
投稿者---si(2006/02/04 03:34:13)


Linux2.6 gcc4.1 でも

x = 1 x *= ( ++x ) ---> 2 * 2 = 4
x = 4 x *= ( ++x ) ---> 5 * 5 = 25

ですね。asm 出力を見たら

   movl  $1, %eax
.L2:
   addl  $1, %eax
   imull  %eax, %eax
   cmpl  $9, %eax
   jle   .L2
です。


この投稿にコメントする

削除パスワード

管理者用メニュー    ツリーに戻る    携帯用URL    ホームページ    ログ    タグ一覧