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

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

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

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

Q&A

解決済

5回答

2933閲覧

(x=y)=5がなぜダメなのか、左辺値の考えで説明

退会済みユーザー

退会済みユーザー

総合スコア0

C

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

0グッド

1クリップ

投稿2020/09/28 13:17

c言語、プログラミングについてです。

左辺値の考えを用いて(x=y)=5がなぜダメなのか理由を説明せよ。という問題です。(漠然とした問題ですが、本当にこのように書かれていて…)

私なりに調べてみました。x=5であれば、「xに5の値を代入する」という意味になり成り立つが、(x=y)=5だと(x=y)は結果であって、左辺値ではないので右辺の値を代入できない、というような説明が散見されました。

このくらいまでしか分かりませんでした。もっと明確な説明にしていきたいのですが、お教え頂けますでしょうか。よろしくお願いいたします。

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

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

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

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

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

guest

回答5

0

ベストアンサー

JISX3010:2003 プログラム言語C

6.5.16 代入演算子

ここに、以下のようにあります。

制約 代入演算子の左オペランドは,変更可能な左辺値でなければならない。

(x=y)=5 は、まず x = y が評価され、y の値となりますy の値が x に代入されます。そして新しい x の値が (x = y) の値となります。次に (y の値)(x の値) = 5 が評価されますが、この時左オペランドは変更可能な左辺値ではありません。

6.3.2.1 左辺値,配列及び関数指示子 左辺値(lvalue)は,オブジェクト型,又はvoid以外の不完全型をもつ式とする(53)。左辺値が評価されたときにオブジェクトを指し示していなければ,動作は未定義とする。オブジェクトがもつ型に言及する場合,その型とは,オブジェクトを指し示すために用いる左辺値によって指定される型とする。変更可能な左辺値(modifiable lvalue)とは,配列型をもたず,不完全型をもたず, const修飾型をもたない左辺値とし,それが構造体又は共用体の場合,const修飾型のメンバ(再帰的に包含されているすべての集成体又は共用体の任意のメンバ又は要素を含めて)をもたないものとする。

演算順序を変えて次のようにした場合、

x = (y = 5)

まず y = 5 が評価されます。y は変更可能な左辺値なので、y に 5 が代入され、評価値は y の値である 5 になります。次に x = 5 が評価されます。この時 x は変更可能な左辺値なので、x に 5 が代入され、評価値は 5 になります。
カッコがなかった場合、代入演算子は右結合なので、x = y = 5 は x = (y = 5) と同じ演算順序になります。

投稿2020/09/28 13:29

編集2020/09/28 23:22
Zuishin

総合スコア28660

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

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

SaitoAtsushi

2020/09/28 13:47

x=y の説明をするなら「代入式は,代入後の左オペランドの値をもつが,左辺値ではない。」という一文も効いてきますね。
kazuma-s

2020/09/28 15:33

> まず x = y が評価され、y の値となります。 左オペランドの値を持つので、x の値となります。 char x = 0; int y = 257; printf("%d\n", x = y); は 1 を表示します。
Zuishin

2020/09/28 21:08

誤解を招く表現でした。確かに x の値ですが、x に代入されたのは y の値なのでそのように表現しました。表現を考え直します。
退会済みユーザー

退会済みユーザー

2020/10/05 12:54

ありがとうございます! 規格に沿って見直してみるととても腑に落ちました!
guest

0

CのJIS規格の 6.5.16 代入演算子 に、

代入演算子は,左オペランドで指し示されるオブジェクトに値を格納する。代入式は,代入後の左オペランドの値をもつが,左辺値ではない。代入式の型は,左オペランドの型とする。

と、代入式の値は「左辺値ではない」と明記されています。
つまりカッコの中は左辺値でないので、代入演算子の左辺に出来ません。

投稿2020/09/28 13:53

otn

総合スコア84499

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

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

0

正確な説明は既にあるので、イメージでの説明を。
=演算子、つまりは、代入とは何か?と考えると、少し見えてくるかもしれません。

C言語において、変数とは、メモリ上に割り当てられてた特定のアドレスに対するラベルのようなものです。
int x,y;等としたときに、コンパイラはメモリ上のアドレスに変数を割り当てます。
例えば、x:0x1000 y:0x1004みたいな感じです。

代入演算子=は、その変数に対して値を書き込む、つまりは特定のメモリアドレスに対して、データを書き込む命令です。
x=5;は、コンパイルされると、こんな感じになります。
[メモリアドレス0x1000 へ 数値5 を 出力せよ]
これが、代入演算子の正体です。

こんな感じに、
代入演算子とは、メモリアドレスに対するデータの書き込み命令である。と思えば、
=の左側は書き込み先の場所を示している必要がある事がわかると思います。

[書き込み先] = [データ]
というのが、代入演算子の書式なのです。

そこから翻って、(x=y)=5を見てみます。
この式は、まず、x=yが実行されます。
これは普通にyのアドレスの値がメモリから読みだされ、xのアドレスにその内容が書き込まれます。
そこまでは問題ありません。
代入演算子にはもう一つ、代入した値を式の値とする。という機能があります。
例えば、y=8だった場合、x=yという式の値は8になります。

x=yが解決したので、残りの部分に取り掛かります。
(x=y)=5ですので、上で実行した結果を受けて、式はこう変化します。
8=5 『数値8へ、数値5を代入せよ』
これは明らかにおかしいと、見てわかると思います。
代入演算子の左側には、書き込み先のメモリアドレスが指定されていなければなりません。

データ(数値)にデータ(数値)は書き込めません。

よって、左辺値がおかしいよ!というエラーになります。


これがもし、x=y=5であれば、問題ありません。
結合法則により、並んだ=は右から解決されます。
y=5がまず実行され、yのアドレスに5が書き込まれます。
さらに、y=5という式の値も5となります。
x=(y=5)は、x=(5)となるので、同じように、xのアドレスに5が書き込まれ、
無事、式の実行は終わります。
(この連鎖的な代入を可能にしているのが、=の式の値が代入結果の値になるという機能です)

投稿2020/09/29 04:23

amiya

総合スコア1218

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

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

退会済みユーザー

退会済みユーザー

2020/10/05 12:59

ありがとうございます!(x = y)は既に結果だから…ということは他にも書かれていましたがモヤモヤしておりました。 8 = 5の例で「結果だから代入できない」という意味が理解できてスッキリとしました。
guest

0

仕様に基づく根拠としては Zuishin 氏の説明がほぼ完璧だと思います。 ただ、質問者の課題はおそらく根拠ではなく考え方を問うものだと思うのでそもそも左辺値とは何であるかという点に重点を置いた回答が妥当でしょう。

変数を評価すると変数に入っている値が得られますが、代入するとき、つまり代入演算子の左辺に現れるときは値を格納すべき場所がわかっていなければなりません。 左辺値として定義されているものは、おおざっぱに言えば値であると同時に場所としての性質をもつものと言えます。 逆に場所としての性質を持たないものが右辺値です。

x=y の演算をした結果は場所としての性質が失われているので値を格納することができないということです。

投稿2020/09/28 13:59

SaitoAtsushi

総合スコア5444

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

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

0

カッコが無ければ良いんですけどね。
変数に値は代入出来ても、式には代入出来ないですよね。

投稿2020/09/28 13:28

hana_yama_san

総合スコア923

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

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問