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

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

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

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

C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

Q&A

解決済

5回答

2416閲覧

演算子の優先度

strike1217

総合スコア651

C

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

C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

0グッド

0クリップ

投稿2017/04/30 01:20

編集2017/04/30 02:14
b = 100; a = ++b; // b = b + 1; a = b; c = b++; // c = b; b = b + 1;

これって変じゃないですか?
演算子の順序は、後置++ < 前置++ < 代入=

a = ++b; b = b + 1; a = b; こちらは、問題ないですよね・・・

#一方は、なんで代入が優先されているのでしょうか??

c = b++; c = b; b = b + 1;

全て演算子がバラバラなので、結合規則は関係ありませんよね?

下のプログラムの例がなんでそうなるのか分かりません。

[追記]

++x || ++y && ++z;

++x が評価され、残りは無視されると思いますが、
一番最初の評価対象が、なぜ++xになっているのでしょうか??
これは、結合規則は、右からですよね?

こちらは、どうなっているのでしょうか??

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

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

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

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

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

guest

回答5

0

ベストアンサー

演算子の働きとして、返り値副作用があります。この2つを区別しましょう(そもそも、前置と後置の意味を逆に捉えていません?)。

  • 前置のインクリメント: 返り値「インクリメント後の値」、副作用「変数をインクリメントとする」
  • 後置のインクリメント: 返り値「インクリメント前の値」、副作用「変数をインクリメントとする」

a = b++;c = ++d;のような代入では、右辺の返り値が左辺に代入されています。

関数でも、「関数内部の処理」と「関数の返り値」は別個の存在ですが、インクリメント・デクリメントに関しても同様です。

投稿2017/04/30 01:29

maisumakun

総合スコア145183

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

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

strike1217

2017/04/30 01:30

ごめんなさい。修正しました。
strike1217

2017/04/30 01:34

つまり、代入が優先されているわけではないということでしょうか?
maisumakun

2017/04/30 01:36

はい、代入演算子の優先順位は最低に近いです。
maisumakun

2017/04/30 01:40

そもそも、インクリメントのほうが優先順位が低ければ、「c = b++;」は「(c = b)++;」と解釈されてしまうはずです。
strike1217

2017/04/30 01:44

(c = b)++; c = b; c++; でしょうか?
maisumakun

2017/04/30 01:50 編集

実際に「(c = b) ++;」を動かそうとすると、「c = b」の結果は右辺値の数値であって、そこへ代入できる左辺値ではないので、コンパイル段階でエラーとなるはずです。
strike1217

2017/04/30 01:53

error C2105: '++' needs l-value 確かに、コンパイルエラーです。
strike1217

2017/04/30 02:01

あ、追記しておきました。
maisumakun

2017/04/30 02:03

追記分ですが、//以降がコメントアウトなら、式として評価される以前の問題ですよね。
Zuishin

2017/04/30 02:11

// でなく || がイタリックになってるみたいですよ。誤解を招くので囲みの初めの ``` を ```C++ とした方がいいです。
strike1217

2017/04/30 02:15

消しました。 分かりにくくて、すいません。
Zuishin

2017/04/30 02:15

すみません。C++ を入れてもイタリックになりました。
maisumakun

2017/04/30 02:18

||の結合法則は「左から右」です。
strike1217

2017/04/30 02:21

&&の方が優先ではないのでしょうか??
strike1217

2017/04/30 02:30

同じ++が並んでいるので、どれが優先されるのか、分かりにくいんですよね
maisumakun

2017/04/30 02:32 編集

&&のほうが優先度が高いので、++x || (++y && ++z)と解釈されます。そして、||は「左辺が0以外なら右辺を評価しない」ので、先に処理されます。
maisumakun

2017/04/30 02:42 編集

「結合の優先順位」と「演算の順序」も、一致するとは限りません(C言語では、&&や||のような一部の例外を除いて、「どんな順序で計算を進めるか」の規定はありません)。
KSwordOfHaste

2017/04/30 02:45

質問やコメントを拝見して感じるのですが、まだ「結合順位」「実行順序」を混同されているように思います。TakeoAsaiさんがコメントされているようにどれを優先して演算するかと実行の順序を区別して考えることができればスッキリするような気がします。
strike1217

2017/04/30 02:45

||は「左辺が0以外なら右辺を評価しない」 なるほど! そういうことですか! 演算子が結構難しい・・・><
strike1217

2017/04/30 02:47

「結合順位」「実行順序」が別物ということですよね? ・・・・? 何が違うんですか??
maisumakun

2017/04/30 02:50

コメント欄が相当に長くなってきましたし、別に質問を立てたほうがスッキリするかもしれないですね。
KSwordOfHaste

2017/04/30 02:53 編集

むむー、A||BでAが成立しない限りBが評価されない点をご存知なかったのですね。どこが疑問なのか把握するのを勘違いしたかも知れません。 A || B && C で、&&が優先だから先に実行すると考えておられたのかと思ったのです。 --- コメント欄が・・・>おっしゃるとおりと思います。失礼しました。
strike1217

2017/04/30 02:55

コメントが長くなってしまいましたね。 「&&が優先だから先に実行する」最初はそうだと思ったのですが、「++」の方が優先度が高しい・・・・と思いまして、 式が長いほど、結局どれが一番最初に優先されるのか分からなくなってしまって・・・
strike1217

2017/04/30 02:59

ORなので、どちらかが0以外であれば当然0以外になるのは、わかるのですが 式全体の評価・・・最終的に式の値がどうなるかが、分からないんですよね。
guest

0

演算子の優先度は、カッコがないときの優先順位であって実行順序ではありません。

つまり

c

1a = b++; 2c = ++b

の優先度をわかりやすくすると

c

1a = (b++); 2c = (++b);

となります。
実行順には無関係なので、b++は代入後インクリメント、++bは代入前インクリメントになります。ややこしいですね。

投稿2017/04/30 01:34

TakeoAsai

総合スコア880

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

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

0

演算子の優先度とは、演算子が何に作用するかを指定するもので、演算子の作用の順番を指定するものではありません。別の言い方をすれば、演算子の優先度は、省略されている括弧をどうつけるかというものです。演算子の作用の順番は、演算子の持っている意味によって決まります。

例として*p++を見てみます。演算子の優先度は++の方が高いので、*(p++)と解釈されますが、もし*の方が高かったら(*p)++になるわけです。*(p++)(*p)++を比べれば、++が作用する対象が違うことが分かると思います。

一方、後置++の意味は、「作用する対象の値を使ってからインクリメントする」ですから、*(p++)なら、先にpの値を取り出して*に渡してから、pをインクリメントします。つまり、pをいつインクリメントするかは、後置++の持っている意味で決まるわけです。

投稿2017/04/30 03:17

退会済みユーザー

退会済みユーザー

総合スコア0

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

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

strike1217

2017/04/30 03:20

作用する対象の値を使ってからインクリメントする なるほどです!
guest

0

プログラミング言語 C 第 2 版の「2.8 インクレメントとデクレメントの演算子」に書いてあることの抜粋をご参考に書いておきます。

****** ここから ******
式 ++n は n の値を使用する前にインクレメントするのに対し、n++ は n の値を使った後にインクレメントするのである。これは、その効果だけでなく、その値を使用する文脈によって ++n と n++ が異なることを意味する。もし n が 5 なら

x = n++;

で x は 5 になるが、

x = ++n;

では x は 6 になる。n は両方とも 6 である。
****** ここまで ******

ということで、

これって変じゃないですか?

質問者さん個人的に変だと思われるのかもしれませんが、質問者さんのコンパイラが上記バイブルの通り実装されているということだと理解すれば納得できませんか?

投稿2017/04/30 02:51

退会済みユーザー

退会済みユーザー

総合スコア0

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

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

0

演算子は本来メソッドを記述すべきところを
簡便する為に特別に定義された短縮記法だったような。(違うかも)
なので厳密には違うと思いますが、こういう雰囲気の理解で良いのでは?

javascript

1var b= 100; 2c=0; 3c= ppb(b); 4console.log('b='+b+' c='+c); // b=101 c=101 5 6var b=100; 7c=0; 8c= bpp(b); 9console.log('b='+b+' c='+c); // b=101 c=100 10 11function ppb(){ 12 b = b+1; 13 rtn = b; 14 return rtn; 15} 16 17function bpp(){ 18 rtn = b; 19 b = b+1; 20 return rtn; 21} 22

投稿2017/04/30 02:40

hirohiro

総合スコア2068

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

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

strike1217

2017/04/30 03:18

簡便する為に特別に定義された短縮記法 そうなんですか!
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問