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

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

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

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

Q&A

解決済

8回答

8540閲覧

変数b=変数aで、なぜaの値はbに入るのか

Heizo

総合スコア16

C

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

7グッド

10クリップ

投稿2020/03/16 07:56

以下のコード、
変数の宣言により、コンパイラーが、変数がメモリのどの部分を使うのか決定する。
そしてa=5により、そのメモリ領域に、値5(2進法の101)が入る。ここまでは直感的に分かるのですが。
b=aにより、bによるメモリ領域に、aの値5が入る所がすっきりしません。
たとえば、bにaが代入される際に、bはaのメモリのアドレスを参照し、そこから値の5を持ってくる。そういう理解で良いのでしょうか。
よろしくお願いいたします。

C

1# include <stdio.h> 2 3int main(void) 4 5{ 6 int a; 7 int b; 8 9 a=5; 10 b=a; 11 12 return 0; 13} 14 15
sawat1203, yamada_yuuki, hoshidash, pentake, kazutarosu, A_kirisaki, yohhoy👍を押しています

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

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

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

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

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

Zuishin

2020/03/16 08:12

この場合は最適化により何もしないプログラムになるかもしれません。ソースがどのようにコンパイルされるかは処理系に依存します。メモリを使うかどうかも決まっていません。今の段階ではコンパイル後の処理を考えるのではなくソースレベルで理解した方が良いかもしれません。a の保持している値が b にコピーされるということだけで十分だと思います。
guest

回答8

0

大変難しい問題です。正しく理解するには、左辺値、右辺値、評価と言ったことがきちんと理解していなくてはなりません。

まず、代入というのは非対象です。式A = 式Bと書かれたとき、式Aを評価した結果である左辺値を式Bを評価した結果である右辺値に束縛します(左辺値が右辺値になると言える)。全ての左辺値は右辺値になることができますが、逆はそうとも限りません。つまり、どのような式も右辺値を返す事ができますが、左辺値を返すことができるのは左辺値式になる式だけです。例えば、aは左辺値式であるため、式Aにも式Bにも書けます。しかし、5は非左辺値式であるため、式Bにしか書けません。

もうわからなくなってきたと思いますが、次はもっとわからなくなると思います。**大丈夫です、私も自分で何を言っているのかわかっていません。**が、取りあえず、続けます。

まずは、左辺値を見てみましょう。aは評価の結果、識別子aが示すストレージにあるオブジェクトです。ストレージはメモリ上のどこかかもしれませんし、CPUのレジスタかも知れませんが、何らかの場所として存在するものです。このストレージはint a;によって作られており、識別子aの名前でアクセスできる場所です。対して、右辺値は単純です。その式を評価した結果のオブジェクトですが、このオブジェクトは何かしらのストレージを持つ必要はありません(もちろん持っても良い)。5という整数リテラル定数は評価の結果、整数で5を表す値(オブジェクト)になりますが、どこかの場所(メモリやレジスタ)に5そのものが保存されている必要はありません。そして、代入は、この左辺値であるところのストレージにあるオブジェクトを右辺値であるところのオブジェクトに(左辺値のストレージに対して)置き換えます(識別子aが示すストレージの場所自体は変わりません)。より単純に言えば、ストレージの中身を右辺値にすると言ってもいいでしょう。こうして、識別子aが示すストレージにあるオブジェクトが整数5に相当する値になります。これがa = 5;の動作です。

次にb = a;を見てみましょう。まずは左辺ですが、先程のaと同様に考えることができて、識別子bが示すストレージにあるオブジェクトです。続いて右辺ですが、先程のaと同じく識別子aが示すストレージにあるオブジェクトです。先程のaは左辺値でしたが、今回は右辺値です。しかし、左辺値も右辺値になれると言ったように、ストレージのあるなしに関わらず、オブジェクトとして解釈できます。ストレージの中身、つまりストレージにあるオブジェクトは先程置き換えた整数5に相当する値です。これで左辺値も右辺値も定まったので、右辺値であるところの識別子bが示すストレージにあるオブジェクトを右辺値である整数5に相当するオブジェクトに置き換えます。こうして、変数bも5になるということです。

なお、左辺と右辺でどちらが先に評価されるかは不定です。左辺が先になる場合もあれば、右辺が先になる場合もあります。順序に依存したコードは未定義の動作になります。


上の話は、ちょっと自信がない所もあります。左辺値と右辺値は言葉で表現するのが本当に難しい所です。Cは単純でありながら、結構曖昧な所もあるので、間違っているかも知れません。C++の方が左辺値右辺値の区別がより厳密に定義されているのですが、複雑ですので、説明しきれる自信はありません。

なお、コンパイラの最適化によって、同じ動作になるのであれば、多くの工程が省かれる場合があります。上の話は実際にコンパイルされた後のコードの話ではなく、言語仕様上の話であることに注意してください。そして、アドレスとかに依存した動作の解釈は正確ではありません。Cの規格上は(ポインタの値を表示するなどの演算がない場合)自動変数のストレージがメモリ上に存在しなくても許されるからです。

投稿2020/03/16 11:16

raccy

総合スコア21739

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

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

Heizo

2020/03/17 00:08

ご回答、ありがとうございますー。 左辺値(代入式の左側)に来る値は、右側に代入できる。一方、逆の場合、右辺値は左側には代入できない。非対称となっている。ここまでは理解できました。 その先の、ここで示されているオブジェクトという言葉のコンセプトが、とらえ切れないまま、読み進みまして。 本質問の場合、a=5の右側の5は「このオブジェクトは何かしらのストレージを持つ必要はありません」というところが、「あ、意外だわ」感がありました。なんとなく、ストレイジには5が入っていると思っていたからです。 で、その先、ストレイジにないまま、ストレイジの中身が右辺値の5になる、というのが不思議だと思ったりしました。 お返事を書くに当たり、ウェッブをググったりして。 末筆になりましたが、(自分なり)考える機会を与えて下さり、ありがとうございますー。
raccy

2020/03/17 09:32

オブジェクトを説明するとそれだけでかなり長い話になります。一つだけ注意点としては、オブジェクト指向言語で言われているオブジェクトと混同しないようにだけお願いします。この概念はオブジェクト指向が生まれる前から(つまりはCがうまれたときには)あった概念です。 5にストレージに無いかもと言うのは、メモリ上のどこかに5が保存されるわけではなく、5という値がCPU命令の羅列であるバイナリコードに直に書かれても構わないと言うことです(`5`というリテラルではありません)。いや、命令コードもメモリ上に展開されるので、正確には、プログラムが操作可能なメモリ空間にはないかもしれないというべきかもしれません。とりあえず、この5は他の何かに置き換えることができないと言うことです。 ぶっちゃけ、私も全てがわかっているわけではありません。K&Rを3回ぐらい読めばなんとなく見えてくるような話です。こういう所を知らなくてもだいたいはなんとかできますが、知っていれば、たぶんきっと、C++とか他の言語の違いとかも理解しやすくなるような気がします。
Heizo

2020/03/17 09:47

コメントありがとうございます。お手数をおかけしております。 ご指摘の通り、混同しておりました。JavaScriptやPythonの参考書でよく目にするオブジェクトと、同様なものとして感じていましたー(もっとも、こちで言うところのオブジェクトも、よく理解してませんが汗) 理解し切れないのですが、あいまいなまま理解しようとしている自分がいたりします。うまく言えませんが。 こういう感じもカーボン紙が重なっていくように、なにかの理解につながることを期待しつつ〜
rubato6809

2020/03/20 01:20

> ストレイジにないまま、ストレイジの中身が右辺値の5になる、というのが不思議だと思った この疑問はアセンブリ言語を学ぶと、ほどなく、喩え話のような・杳としたものでなく、確実な・リアルな・そのものズバリなモノを知ることになり、理解できるはずです。アセンブリ言語をお勧めする理由です。
Heizo

2020/03/20 06:27

コメント、ありがとうございますー。勉強してみたいと存じますー。
raccy

2020/03/20 06:34

アセンブリでの解説版も別回答として書きました。参考にしていただければと思います。
guest

0

既にした回答と方向性が異なるので、別回答としています。


コンパイル後のバイナリコード(機械語)においてどのようCPU命令になっているのかを確認することはCそのものというより、Cのコードが実際にコンピューター上でどのように実行されるのかを理解する上では有用です。機械語を直接理解するのはちょっと難しい(できる人はできるらしい)ので、機械語と一対一対応しているアセンブリにおいてどうなっているのかを見たいと思います。

Cのコードをアセンブリに変換したコードを見るにあたって、注意事項が二点あります。

  1. RISCアーキテクチャCPU向けのアセンブリを使う方が原始的な動作の理解がしやすい。
  2. 最適化を無効にする。

まず、CPUは大きく分けるとCISCとRISCにわかれます。例えばx86(およびその拡張であるx86_64)はCISCですが、SPARCやPowerPCはRISCです。RISCは非常に単純な命令しか用意されていませんが、CISCはより複雑な命令が用意されています。と言ってもRISCがCISCより劣るというわけではなく、RISCで複数の命令になるようなものをCISCでは一つにまとめた便利命令みたいな感じで用意しているだけです。CISCでのアセンブリを見た場合、RISCで複数の命令になるようなものが一つ命令にまとめられてしまっている場合があります。しかし、実際の所一つの命令でもCPU内部では二つ以上の処理を行っている場合もあるため、命令の一つをCPUの原始的な動作としてしまうには問題があると思います。なお、現在のCPUは、CISCであっても中身がRISCだったり、RISCであってもCISC並の命令が用意されていたりと、その垣根は曖昧になりつつあります。

今回は、コンパイル環境の構築が容易であり、また、後述の確認サイトで使えて、一般的にRISCに分類されるCPUの一つであるARM64(64bit版のARM)をターゲットにしたいと思います。ARM64のアセンブリを調べるにはARM® コンパイラ armasm ユーザガイド バージョン 6.02を参考にしました(でも、微妙に違うような…コンパイラがGCCだから?)。日本語版があってよかったです。

つぎに、最適化についてですが、Cでは最適化によって結果が同じになる場合は、処理が省略されたり、まとめられてしまうことはよくあることです。とくに、使用されない変数は、そもそも消される場合が多いです。最適化による省略などを防ごうとするのであれば、次のように使用されることを強制する方法もあります。

C

1# include <stdio.h> 2 3int main(void) 4 5{ 6 int a = 0; 7 int b = 0; 8 printf("%p: %d\n", &a, a); 9 printf("%p: %d\n", &b, b); 10 a = 5; 11 printf("%p: %d\n", &a, a); 12 printf("%p: %d\n", &b, b); 13 b = a; 14 printf("%p: %d\n", &a, a); 15 printf("%p: %d\n", &b, b); 16 17 return 0; 18}

しかし、これでも処理の順番やスタックの位置が前後したりすることは防ぐことはできません。なので、アセンブリで確認する場合は最適化無しで確認した方が良いでしょう。ただ、最適化した場合だけ発生する不具合のバグ取りなどは最適化した状態でみないと意味が無いと言うこともあります。今回は動きの確認だけが目的ですので、そのような問題は無視しても良いでしょう。

さて、これらを踏まえて実際にアセンブリに変換するのですが、わざわざARM64ターゲットを含めてコンパイラをインストールしている人も少ないでしょうから、オンラインで確認できるCompiler Explorerを使います。お手軽に確認ができるのでとても便利なサイトです。

質問コードのアセンブリ変換結果

対応するコード同士が色別されているため、何がどの部分にあたるのかを視覚的にわかるのもこのサイトの良いところです。

まず、a=5;は次のコードです。

mov w0, 5 str w0, [sp, 12]

最初のmovは値をレジスタへ移動します。w0は0番目の32ビット汎用レジスタです。1番目の命令は5という値を0番目の32ビット汎用レジスタに32bit分移動することを表します。移動とは言ってますが、実際はコピーです。次のstrはレジスタの値を指定位置のスタックポインタを転送します。w0は先程同じです。[sp, 12]はスタックポインタから12個先の位置を表し、後述しますが、これはローカル自動変数aの保存領域です。つまり、0番目の32ビット汎用レジスタの値をスタックポインタから12個先の位置に32bit分転送することを表します。

スタックポインタというのがでてきました。これは最初のsub sp, sp, #16によって16個後ろになっており、この16個分の領域が関数内で色々操作できる領域となり、ローカル自動変数abの保存領域として使われます。

関数内でのスタックポインタを00(16進数)とすると次のようなイメージになります。

0000 0000 0000 0000 11... 0123 4567 89AB CDEF 02... S <b > <a > R

Rは関数が呼び出される前のスタックポインタで、Sは関数内で処理されている最中のスタックポインタです。スタックは後ろから使われるため、a用に0C-0F、b用に08-0Bが確保されます。今回の関数では00-07は使用されません。ローカル変数がもっと多ければスタックが埋まっていきますが、ARM64では16バイト毎に確保するようになっているようで、intが5つ以上になると32になったりします。どの区切りで確保されるかや、スタックポインタの扱い方はCPUのアーキテクチャによって異なります。あくまで、これはARM64の話であることに注意して下さい。

さて、話は戻ってb=a;です。

ldr w0, [sp, 12] str w0, [sp, 8]

最初のldrstrの逆、指定位置のスタックポインタの値をレジスタに転送します。w0[sp, 12]は先程と同じです。つまり、スタックポインタから12個先の位置の値を0番目の32ビット汎用レジスタに32bit分転送することを表します。先程あったstr w0, [sp, 12]と逆の動作で、無駄なことをしているように見えますが、最適化が無効の場合は無駄なことを省かないようになります。次のstrは先程見たのと同じです。w0はもう説明不要でしょう。では、最後の[sp, 8]は何かというと、スタックポインタから8個先の位置を表し、先程の説明にあった通り、これはローカル自動変数aの保存領域です。つまり、0番目の32ビット汎用レジスタの値をスタックポインタから8個先の位置に32bit分転送することを表します。

後の処理はreturnの値をセットしてスタックポインタを元に戻して、元の関数に戻ると言うだけになります。

ふー、たった二行だけなのに、長かったです。少しでもCのコードが実際はどんな機械語になって、CPUは処理しているのか理解していただけれたら幸いです。ただ、スタックの取り方とか、レジスタの扱い方とか、そういうところは、考え方はだいたい一緒ですが、実際の方法がアーキテクチャによって大きく異なる場合があるので、注意して下さい。


今回、私は始めてARMのアセンブリに触れました。x86等も含めてアセンブリで書くこともないですし、読むことも非常に稀です。なので、アセンブリに詳しい専門家の方から見たら間違っている部分があるかも知れません。コメント等でご指摘下さい。

今回のようなことは、アセンブリ超初心者の私でもできたので、単純なコードであれば、アセンブリでの解析は誰でもできると思います。たぶん。

投稿2020/03/20 06:33

編集2020/03/20 06:44
raccy

総合スコア21739

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

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

rubato6809

2020/03/20 11:06

この回答に質問者は感謝すると思いますが、私も感謝を表明したいと思います。 質問者へ: > 1番目の命令は5という値を0番目の32ビット汎用レジスタに32bit分移動する > mov w0, 5 この命令に見える「5」が「どこかの場所(メモリやレジスタ)に5そのものが保存されている必要」がなかった「5」であり、私が「ほどなく…そのものズバリなモノを知ることになる」とコメントした命令です。こんなにもほどなく(笑)伝えられるとは考えていませんでした。もっとも、私が想定していたのはARMではなくx86のアセンブリコードでしたけど、案ずるより産むが易しとはこのことですね。。。 これを見ただけで質問者が理解できるということにはならないだろうけれど、この mov 命令を含む数命令だけでもコンピュータの仕組みを具体的に理解する手がかりになるでしょう。 Enjoy !
Heizo

2020/03/22 00:00

コメント遅くなってしまい恐縮です。 現在、解説に際して、不明な点をウィキペディア等のウェブで調べたり、コードを実際に打って確かめてみたりしております。 これから(たぶん)理解も進み、本件周辺に出逢った際には、また立ち戻って再読していきたいと存じます。 お手数をおかけしております。ご回答、ありがとうございますー。
guest

0

代入演算子 = は 2項演算子で、第1オペランド(左辺) には
値を入れる入れ物を要求し、第2オペランド(右辺)には値を要求します。

定数、変数、「演算子を使った式」はどれも「式」です。そして値を持ちます。
だから、右辺に置けるのです。

定数は値を持ちますが、値を入れる入れ物ではないので、左辺にはおけません。

変数は値を入れる入れ物であり、値も持ちます。
だから、左辺にも右辺にも置けるのです。
左辺に置いた場合、その値は要求されません。入れ物であることが要求されるのです。

a + 7 のような演算子を使った式は、演算結果の値を持ちますが、
それは入れ物ではありません。a が 5 のとき、a + 7 は 12 です。
a + 7 は入れ物ではなく、そこに別の値を入れることはできません。
a + 7 = 3 とは書けないのです。

では左辺には変数しか置けないのか言うとそんなことはありません。
a[i] は、 添字演算子 [ ] を使った式ですが、これは入れ物です。
*p は間接演算子 * を使った式ですが、これは入れ物です。
だから、a[i] も *p も左辺にも右辺にも置けるのです。

a = b を「変数 a に変数 b が入る」というのは不正確な表現です。
「変数 a(という入れ物) に、変数 b(という入れ物)から取り出した値が入る」
というのが正確な表現です。

もう一度言います。
代入演算子は、左辺の入れ物に、右辺の値を入れます。

定数 5 は、値そのものです。
変数 a は、入れ物ですが、値を取り出せます。

なお、入れ物のことを左辺値と呼びます。

投稿2020/03/17 12:17

kazuma-s

総合スコア8224

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

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

0

bはaのメモリのアドレスを参照し

"bは" という表現に引っかかりました.
オブジェクトとして考えるとそのような表現もあるかと思いますが, それは考えすぎとも思います.

「a=5」はコンパイラが「a(のアドレス)に5を入れる」と解釈して該当するアセンブラコードを生成し,
「b=a」はコンパイラが「b(のアドレス)にa(のアドレス)の値を入れる」と解釈して該当するアセンブラコードを生成する
...という"感じ"でしょうか.

投稿2020/03/16 09:08

jimbe

総合スコア13209

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

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

Heizo

2020/03/16 09:16

クリアなご回答、ありがとうございます。 アドレスの経路をたどっていくで、なんとか、頭が整理できそうですー。
guest

0

ベストアンサー

たとえば、bにaが代入される際に、bはaのメモリのアドレスを参照し、そこから値の5を持ってくる。そういう理解で良いのでしょうか。

はい、その理解で合っていると思います。

投稿2020/03/16 08:08

nskydiving

総合スコア6500

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

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

Heizo

2020/03/16 08:23

ご回答ありがとうございますー。
退会済みユーザー

退会済みユーザー

2020/03/17 06:36

俺たち正解してるのにマイナス評価なの悲しいよな。
maisumakun

2020/03/18 02:18

C言語の変数はメモリに割り付けられるとは限りません。最適化で吹き飛ぶ場合は別にしても、レジスタに入れたままで処理が進むことも考えられます。
HidekoSaeki

2020/03/23 23:46

変数は必ず宣言が必要です。つまり主記憶に領域が確保されているのです。定数も主記憶に領域が確保されています。
Zuishin

2020/03/23 23:57 編集

主記憶の意味が不明です。主記憶とは通常、単にメモリと呼ばれることの多い主記憶装置の領域を指します。 http://www.wisdomsoft.jp/351.html > レジスタ変数の注意点としては、レジスタ変数は主記憶に配置されないというのが原則なので、アドレスを求めることはできません。
guest

0

既に多くの方が良い回答をなさっていますので、わたしなりに自分の考えをまとめるために回答させていただきます。

b=aにより、bによるメモリ領域に、aの値5が入る所がすっきりしません。

の部分の理由がはっきり書かれていないので、そのあたり憶測になり的外れな答えかもしれません。
結論を先に言えば

  1. プログラムの数式は、数学の様式を一部借りてはいるが数学の数式とは別のものである
  2. 変数という概念を導入した以上、変数同士で値の受け渡しは必ず必要になり、C言語では、a = b という書式が選ばれた

数学の数式が、数学的事実の表記を目的としているのに対して、
プログラムの数式は(プログラムの他の部分同様)処理の手順を示しています。
そして、C言語等においては計算の手順を記載するうえで、

b = a

という形式が都合がいいとの判断から、数学の数式との意味の齟齬は無視されたのです。
実際、私が最初にこの言語仕様に出会った時思ったことは、「便利だな」「なるほどそうやるのか」程度で、質問者の方が持たれたような疑問は(数学の成績が悪かったせいか)あまり考えませんでした。

ただ、当時から「b = a」という記述方法しかなかったわけではなく、
代入の意味を明確にするために、代入記号に「:=」を使ったり、「LET」や「SET」と言ったキーワードを使って明確に代入を示す記法も存在しました。

C言語登場以降、大型計算機からより小型のPCなどへの計算機利用の移行という流れの中で、
C言語スタイルのシンプルな記述形式は流行し、
LET などのキーワードを省略可にしたりする言語も現れましたが、
PCの能力が往時の大型計算機に迫り、追い抜くようになってくると、
可読性や厳密性のために、こういった代入の書式を見直す言語も増えてきました。

いずれにしろ、プログラム一般において「変数から変数への代入」という処理の必要がまずあって、
書式はそれをどう表現するのがいいかを(それぞれの言語設計者がそれぞれの考えで)
後付けで考えて決めたものです。
その際に数式や英文の形式を借りてはいますが、そのままの意味であるとは限らないので
他所での解釈は一旦棚上げして考えるのが、プログラム言語を理解する早道だと思います。

投稿2020/04/15 00:08

編集2020/04/15 07:13
kozuchi

総合スコア1193

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

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

Zuishin

2020/04/15 02:04

F# は新しい言語ですが、let が必要です(代入ではなく束縛ですが)。C 言語は古い言語ですが、let は不要です。レガシーかどうかではなく、その言語のポリシーによるものでしょう。 VB では = が代入と比較の両方の演算子を兼ねており、文脈で意味が変わります。C の == よりコンパクトですが、しばしば批判の種になります。 代入用のキーワードではありませんが、JavaScript では変数の宣言に var const let があります。そのいずれもつけなくともプログラミング可能ですが、冗長なキーワードを使うことによってより保守性の高いコードを書くことができます。 C# や Java は C よりも新しい言語ですが、Hello World を書くのに C より冗長なエントリポイントを書かなくてはなりません。 多くの言語で let や set が無いのは、もちろん冗長を嫌ったということではありますが、それはモダンだからではなく、他の言語に倣って文法規則を選んだというだけでしょう。むしろ let や set を使うモダンな言語がこれから登場する可能性も十分あります。
kozuchi

2020/04/15 06:07

なるほど、おっしゃることはほぼその通りだと思います。 C言語の話題だったので、C言語が登場した時代を前提に考えていましたが、その後さらにさまざまな言語がさまざまな考え方で登場していますね。 C言語の時代にも Pascal 等は := で区別していたりしましたし。 そのあたりのことを含めて後半部分は書き直します。
pepperleaf

2020/04/15 12:09

質問は、書式/記法の問題じゃないと思います。 と書きつつ、 また、Zuishinさんの > 多くの言語で let や set が無いのは、...、他の言語に倣って文法規則を選んだ と思います。今、主流の多くは、C言語の影響が強いです。当初、C言語は貧弱なマシンでの動作でした。(少ないパスでのコンパイルとか) その一方、最近の流行は、若干、冗長な方向に進んでいるように感じますね。 設計思想と言えば、COBOLは、容易な英語表記を想定していたようです。足し算は、ADD とか。で、数式をそのまま、書く場合は、COMPUTE が必要でした。(最近のは知りませんが)
kozuchi

2020/04/15 16:33

その点については、私は最初に > >b=aにより、bによるメモリ領域に、aの値5が入る所がすっきりしません。 > の部分の理由がはっきり書かれていないので、そのあたり憶測になり的外れな答えかもしれません。 と書きました。 あなたの言う通り、書式/記法の問題ではなく(私は書式/記法の問題だと言ったつもりはないですが)私の答えは的外れかもしれませんし、私の書いたことにも何らかの意義があるかも(ないかも)しれません。 それは最終的には質問者の方にしか判断できないことでしょう。 Zuishin さんのコメントには明確な誤りの指摘があったので訂正しましたが、この話題をここでこれ以上続ける意味を感じません。
guest

0

たとえば、bにaが代入される際に、bはaのメモリのアドレスを参照し、そこから値の5を持ってくる。そういう理解で良いのでしょうか。

代入文b = aをなるべく言語仕様に合わせた用語で解釈すると、「識別子aが指し示すデータ記憶域に保持された値5で、識別子bが指し示すデータ記憶域の内容を置き換える」となります。
より質問中の表現に近づけると「変数aのメモリ領域に入っている値5を読み取り、変数bのメモリ領域にその値を入れる」でしょうか。

言語仕様にて規定されるプログラムの振る舞いは上記の通りですが、実際にはCコンパイラによる “最適化” が行われます。質問中ソースコードの場合、プログラム外部から観測可能な入出力をもたないため、結果的に下記のような「何もしないプログラム」まで最適化される可能性があります。

C

1int main() { return 0; }

日本工業規格(JIS) X 3010:2003 プログラム言語C、その翻訳元である ISO/IEC 9899:1999 Programming languages - C より、直接関連する文面を引用しておきます。

§3. 用語及び記号の定義/Terms, definitions, and symbols
バイト(byte)
実行環境の基本文字集合の任意の要素を保持するために十分な大きさをもつアドレス付け可能なデータ記憶域の単位。
addressable unit of data storage large enough to hold any member of the basic character set of the execution environment
オブジェクト(object)
その内容によって,値を表現することができる実行環境中の記憶域の部分。
region of data storage in the execution environment, the contents of which can represent values
値(value)
オブジェクトが特定の型をもっていると解釈する場合のオブジェクトの内容の厳密な意味。

precise meaning of the contents of an object when interpreted as having a specific type

§6.3.2.1.
左辺値(lvalue)は,オブジェクト型,又はvoid以外の不完全型をもつ式とする。
An lvalue is an expression with an object type or an incomplete type other than void

変更可能な左辺値(modifiable lvalue)とは,配列型をもたず,不完全型をもたず, const 修飾型をもたない左辺値とし,(後略)
A modifiable lvalue is an lvalue that does not have array type, does not have an incomplete type, does not have a const-qualified type, [...]

§6.5.16.
代入演算子の左オペランドは,変更可能な左辺値でなければならない。
An assignment operator shall have a modifiable lvalue as its left operand.

単純代入(simple assignment)(=)は,右オペランドの値を代入式の型に型変換し,左オペランドで指し示されるオブジェクトに格納されている値をこの値で置き換える。
In simple assignment (=), the value of the right operand is converted to the type of the assignment expression and replaces the value stored in the object designated by the left operand.

注釈) 左辺値という名前は,代入式E1 = E2から由来している。すなわち,代入式の左のオペランドE1は,(変更可能な)左辺値となる必要がある。左辺値は,オブジェクトの位置を示す値を表現するものと考えたほうがよいかもしれない。時として右辺値と呼ばれるものは,この規格においては式の値として記述する。左辺値の最も明確な例は,オブジェクトの識別子である。(後略)
The name "lvalue" comes originally from the assignment expression E1 = E2, in which the left operand E1 is required to be a (modifiable) lvalue. It is perhaps better considered as representing an object "locator value". What is sometimes called "rvalue" is in this International Standard described as the "value of an expression". An obvious example of an lvalue is an identifier of an object. [...]

投稿2020/03/19 06:49

編集2020/03/19 06:53
yohhoy

総合スコア6191

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

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

0

解決済みですが誰も書いてないので書きます。

そのソースコードをコンパイルしたらどんなプログラムになるかは、アセンブリ言語にコンパイルして中身を読むと分かるでしょう。

投稿2020/03/17 00:27

退会済みユーザー

退会済みユーザー

総合スコア0

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

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

Zuishin

2020/03/18 04:04 編集

コンパイラによって違う結果になります。主要コンパイラとそのそれぞれのターゲット、そして最適化オプションを使ってのコンパイル結果を比較した回答なら高評価されたと思いますが、これだけでは「分かるでしょう」という結論が間違いなので低評価にしかなりません。
退会済みユーザー

退会済みユーザー

2020/03/18 06:42

間違ってないです。そんな理由で低評価してるなら取り消してついでにアカウントも消してください。
Zuishin

2020/03/18 06:46

なるほど、処置なしですね。
退会済みユーザー

退会済みユーザー

2020/03/18 06:46

「コンパイラによって違う」という点だけ合ってます。だから「このコンパイラではどんな機械語に翻訳されるんだろう?」と気になったら「アセンブリ言語にコンパイルして中身を読んでみよう」ってなるんです。何も間違ってない。
退会済みユーザー

退会済みユーザー

2020/03/18 06:48

やっぱ無料で回答してる人に対して自分は何も回答せずに低評価ポチポチしてるやつはどこか頭のネジが抜けてますね。
Zuishin

2020/03/18 06:49

ご苦労様です。
Zuishin

2020/03/18 07:12 編集

ああそうだ、いいことを思いつきました。 あなたの主張はこういうことでしょ? 私を含む頭のネジの外れた四人が低評価し、まともな判断のできる人は誰もあなたの回答を見ていない。 だったら話は簡単です。ツイッターでも何でもまともな技術者のいそうなところで宣伝すればいい。そうすればまともな人の目について高評価が低評価を上回るはずです。 私は低評価が増えるだけではないかと思いますが、頭のネジが外れた人の判断はあなたにとって無意味でしょう? 頑張ってください。
kyoya0819

2020/03/18 14:29

Zushinさんと同じ理由で低評価。 少なともあなたよりは頭のネジがしまってます。
退会済みユーザー

退会済みユーザー

2020/03/19 00:27

出たasuchi(笑)落ち着けって
Zuishin

2020/03/19 01:21

あなたこそ落ち着いて低評価が倍になっていることを受け入れてください。
rubato6809

2020/03/20 01:10

「a の保持している値が b にコピーされるということだけで十分だと思います(Zuishinさん)」を回答にすればよかったのに、回答のひとつとして悪くないのに、と思いました。アセンブリ言語を見るまでもないという立場から低評価をつける気持ちはわからないでもないし、評価は人それぞれですが、ただマイナス8という評価には異常なものを感じます。 LGBTさんの回答に対する私の感想は、高評価をつけるまでではないが、アセンブリ言語に言及したのはよかったなということです。アセンブリ言語を知ることでC言語がより確実に理解できることは多くの人が実感している事だからです。不可解な現象がアセンブリ言語レベルで理解できる事は少なくありません。私も質問者に、どこかでアセンブリ言語に触れてみることをお勧めしたい。 だとすると今回、Zuishinさんと私のアセンブリ言語に対する立場は、昨年秋と逆転した格好ですのでお断りしておきますと、LGBTさんは最初からセカンドオピニオン的位置づけで回答されていますのでマイナス評価する必要は無いと思います。普通こうした問いに対する回答はひとつではありませんから。
Zuishin

2020/03/20 02:12 編集

逆転というのがおかしいですね。状況が違います。低評価がおかしいと個人的に思うなら高評価すればいいのではないですか? 私が 8 つも付けたわけではありません。
kazuma-s

2020/03/20 03:56

質問 この英文をこう解釈したのですが、そういう理解でよろしいでしょうか? 回答 中国語に翻訳してもらって、それを見ればよいでしょう。 質問者がアセンブリ言語を熟知していると仮定する回答は低評価になると思います。
rubato6809

2020/03/20 04:07

> 熟知していると仮定する 逆です。中国語を知らないだろうけど中国語を学んで新しいビジネスチャンスを見つける道もあるよ・・・みたいなことです。
Zuishin

2020/03/20 04:08

それしかなかいならそれしかありませんが、今回はそうではありません。
Zuishin

2020/03/20 04:16

> そういう理解で良いのでしょうか。 これが質問です。 コンパイル後のアセンブラを見て、たまたま自分の思っていた通りになるということもあるでしょう。そこで理解していいんですか? これはたとえば、初期化されていない変数を使ってたまたま思い通りになったとして、それでいいと思い込むようなものです。
Zuishin

2020/03/20 04:21

「サイコロを振れば六が出るという理解でいいですか?」という質問に「一回振ってみたらわかる」と答えるようなものです。 最初に書きましたが、複数の条件でどうなるか比較した回答であるなら高評価が得られたと思います。しかしこれでは低評価にしかなりません。
rubato6809

2020/03/20 04:41

> たまたま自分の思っていた通りになるということもあるでしょう。そこで理解していいんですか? へえw「アセンブリコードに直してから研究してください。でなければ・・・」と書いた同一人物とは思えませんねえ。 そりゃあ、誤解することだってあるでしょう。でもそれを恐れていたら何もできないでしょうね。どんな言語を学ぶにしても最初の一歩があります。私自身、様々な誤解や回り道や間違いをしながら大きくなりましたよ笑。 > 複数の条件でどうなるか比較 はい。それは面白い研究になるでしょうね。
Zuishin

2020/03/20 04:43

この二つが同じ条件だと思っていることで、あなたが何もわかってないことがわかります。あなたの机上の空論はあなたの脳内評価でしかありません。
Zuishin

2020/03/20 04:45

私は夏は「暑い」と言うし冬は「寒い」と言います。同一人物ですが。あなたと違って現実を見るからです。
Zuishin

2020/03/20 04:47

逆にあなたは人に反対するためだけに人と逆のことを言っているようですね。そういうのをなんと言うかご存じでしょうか? 天邪鬼といいます。
fana

2020/03/20 04:56

(回答に対する評価はともかく,「昨年秋がどうの」とか「同一人物がどうの」とかいう個人間にしかわからないノイジーな話に関しては,ここでやるべきではないのでは?)
Zuishin

2020/03/20 05:09 編集

昨年秋だったかいつだったかどうでもいいので覚えていませんが、彼はなぜかハイテンションで色々な人にけんかを売っており、そのうち一人が私でした。そして彼の回答が低評価の沼に沈み、そのことを根に持っているようです。 その復讐が彼の本題で、この回答は材料にすぎません。この回答を特に評価していないことは高評価が一つも増えていないことでわかります。まあ季節の変わり目にはこういうこともありがちです。
退会済みユーザー

退会済みユーザー

2020/03/26 07:51

-13ってギネス記録じゃね?
kyoya0819

2020/03/26 08:17 編集

ギネス世界記録の認定・登録基準に達していないため、認定・登録はされないです。
退会済みユーザー

退会済みユーザー

2020/03/26 08:50

強い...!
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.35%

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

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

質問する

関連した質問