🎄teratailクリスマスプレゼントキャンペーン2024🎄』開催中!

\teratail特別グッズやAmazonギフトカード最大2,000円分が当たる!/

詳細はこちら
C

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

C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

Q&A

解決済

4回答

1138閲覧

C言語の式の途中のインクリについて

sadokazu

総合スコア14

C

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

C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

0グッド

0クリップ

投稿2019/11/17 00:57

C言語のインクリで質問があるのですが、

c#

1byte[] data = new byte[2]; 2data[0] = 100; 3data[1] = 200; 4 5int i = 0, c = 0; 6 7c = data[i++] + data[i];

c#では答えは300となりますが、

C

1unsigned char data[2]; 2data[0] = 100; 3data[1] = 200; 4 5int i = 0, c = 0; 6 7c = data[i++] + data[i];

Cでは200となります。

c = data[i + 0] + data[i + 1]
と記述すれば300となりますが、C言語は式の途中でインクリされないのですか?

Bitmapをグレースケールに変更する部分ではまってしまい、気になったので投稿しました。
よろしくお願いします。

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

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

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

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

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

guest

回答4

0

投稿2019/11/17 01:18

cateye

総合スコア6851

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

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

0

ベストアンサー

C言語は式の途中でインクリされないのですか?

されるかもしれないし、されないかも知れません。コンパイラによる、と言っていいでしょうか。

C#の詳細は知りませんが、少なくともCでは、i++でのインクリメントがいつ実行されるかは処理系依存です(「ココまでには完了している」という規定はありますけれど)。

ですから、演算子の副作用で値を変える変数を同じ式中で別に参照することはC言語においては文法的には許されていても運用として「禁じ手」とされるのが普通です。


一応Cの規格書(JIS)にあたってみました。未定義とも処理系依存とも書いてはいませんでした。

6.5.2.4 後置増分及び後置減分演算子

<略>
オペランドに格納されている値を更新する副作用は,直前の副作用完了点から次の副作用完了点までの間に起こらなければならない。

とだけ。

投稿2019/11/17 01:14

編集2019/11/17 01:26
thkana

総合スコア7703

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

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

sadokazu

2019/11/17 01:27

C言語はまだ初心者でドハマリしてしまっていました。 詳しい説明ありがとうございます。
maisumakun

2019/11/17 01:32

その直後に「変更前の値の読取りは,格納される値を決定するためだけに行われなければならない」という条件があって、今回のコードはこちらに違反するので未定義動作となるのではないかと思います。
sadokazu

2019/11/17 01:39

今回の件で式を明確にする必要があるということを認識しました。 ありがとうございます
thkana

2019/11/17 02:06

> maisumakun え? 直後にそんなの書いてない、と焦ってしまいました。C++の規格の話なら、一応そう前置きしていただけるとありがたいかと。(この辺の話って、突っ込まれポイントが多いので、結構ビクビクしながら回答してます) JISX3014の5.式の4のところでしょうか。 --- 特に断らない限り,それぞれの演算子の演算対象間の評価順序,それぞれの式の中の部分式の評価順序 及び 副作用の発生順序については,規定しない。一つの式の評価によってスカラオブジェクトの格納値が変わるのは,高々1回でなくてはならない。 更に,直前の値は,次に格納すべき値を決定するためにだけアクセスされる。<略>そうでない場合,その挙動は未定義とする。 --- とりあえずCでは「未定義」(何が起こっても不思議ではない)とする明確な根拠を私は見つけていませんが、「プログラマはそういう式を書くな」という点では一致しているかと思います。
guest

0

c = data[i++] + data[i];

副作用完了点:「i++の副作用:"iを1増やす"が働くところ」は
少なくとも上記の;に至るまでのどこか と規定されています。

data[i++]の直後とは限りません(コンパイラの勝手です)。

投稿2019/11/17 01:20

episteme

総合スコア16612

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

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

0

その場合の結果は不定となります
なので、何が返ってきても文句は言えません

投稿2019/11/17 01:05

y_waiwai

総合スコア88038

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

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

maisumakun

2019/11/17 01:07

未定義の動作、かと思います。
y_waiwai

2019/11/17 01:31

まーそこらへんは難しいところで、規格上では何が起こっても不思議ではないとなってても、実際の実装ではこれで暴走するような処理系ってのは考えられないわけで、そこらへん初心者に教えるときはちと難しいところではあります
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.36%

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

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

質問する

関連した質問