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

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

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

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

ポインタ

ポインタはアドレスを用いてメモリに格納された値を"参照する"変数です。

C++

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

Q&A

2回答

637閲覧

C言語のポインタ変数に関節演算子をつけた時に保存されるメモリ領域について

abct

総合スコア3

C

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

ポインタ

ポインタはアドレスを用いてメモリに格納された値を"参照する"変数です。

C++

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

0グッド

0クリップ

投稿2021/09/08 17:24

C言語でポインタ変数に関節演算子をつけると、保存先はそのポインタ変数に代入されているアドレスと聞いたのですが、2つの変数で同じメモリを共有するというのがよくわからないです。わからない理由として、OSはアプリケーションごとにメモリを割り当てる理由が同じメモリの領域を共有すると問題が発生するのに、なぜ変数はいいのかなどです。
自分で調べましたが、大体のサイトには保存されるアドレスの話まではいっていなかったので質問しています。

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

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

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

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

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

jimbe

2021/09/08 17:29 編集

関節?間接? 同じメモリを指すのは1つのプログラム内でのことで、アプリケーション間ではありません。
dodox86

2021/09/08 18:25

実際にご自身でコードを書いて体感してみないと分からないのかもしれませんね。ポインタ変数に入っている値をアドレスとしてその位置のメモリにアクセスしているだけで、例えばAとBと言う2つのポインタ変数の中に同じアドレスが入っていたとしてもそれだけでは「共有」と言う意識は無いです。 共有を意識するのはプログラマーやプログラミング言語、それらのサポートする関数、OSなどの話になってからです。 具体的にどんなコードで不思議に思っているのか、コードを提示すれば具体的な回答をもらえるかもしれませんよ。
kaina

2021/09/09 06:27

多分、文章だけだとabctさんが聞きたいことと回答者が理解したことに差異が発生しているように思われます。 dodox86さんも指摘されていますが、簡単なコードで良いので具体例を示して下さい。
fana

2021/09/10 01:23

> 問題が発生する と言う表現は漠然としすぎている.もっと具体的に 「○○な状態で××が△△したら,□□ってことになっちゃうから問題だよね」 とかいう形で述べられたい. で,そのような形で何かしらの懸念事項が考えられるとしたら,逆に言えば, 「○○な状態で××が△△しないならば」その問題は起きない(回避できる)のだから, そのように気を付けて使うならば「共有」したっていいんじゃない?
退会済みユーザー

退会済みユーザー

2021/09/10 14:44 編集

前回も漢字の間違い指摘されてるのに修正してないので、日本語が読めないのかもしれない。
guest

回答2

0

C言語でポインタ変数に関節演算子をつけると、保存先はそのポインタ変数に代入されているアドレスと聞いた

まず大前提です。
C言語では、変数名で直に指定できない変数データを扱うために「アドレス」という概念があって、「このアドレスにあるデータ」というのを ¥* 演算子等で指定できるわけですが。
しかし、これはC言語上の概念であって、「コンピュータ上のメモリアドレスを指定してメモリを書き換えられます」と言ってるわけではないです。両者を混同してはいけません。
※変数名で指定できない … 例えば、関数 f 内のローカル変数 x に、関数 g の中で値を保存しようとしても、x という名前は使えません。そうでなくても、malloc で確保した領域のデータはそもそも名前がついていません。

そうは言っても「C言語としてのアドレス」を実現する仕組みは必要で、それは多くの場面で「機械語から操作するメモリアドレス」になります。なので、プログラムXの中でメモリ0x1000000番地を操作、プログラムYからも同じ0x1000000番地を操作と、一見競合を起こすかのように見える場面も出てきます。

しかし、それで競合が起こらないように、LinuxなりWindowsなりの汎用的な環境では、CPUとOSが連携している「仮想メモリ」という仕組みが動いています。
機械語で扱うメモリアドレスは「論理アドレス」で、そこから動いているプログラム毎に違う変換テーブルを用意して、別々の「物理メモリアドレス」が裏で使われるようになっています。なので、競合が起こりません。

詳しいことは「仮想メモリ」で調べてみてください。ただ、アーキテクチャの理解という意味で知識はあって良いと思いますが、C言語を扱う上では脱線の話ですので、そこは注意してください。

投稿2021/09/08 23:07

angel_p_57

総合スコア1672

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

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

abct

2021/09/09 05:12

つまり、C言語では機械語などで操作するコンピュータのメモリとは違うということですか?
angel_p_57

2021/09/09 12:44

> 違うということですか? はい。違います。というより、分けて考えましょう、ということです。 「そうは言っても『C言語としてのアドレス』を実現する仕組みは必要で、それは多くの場面で『機械語から操作するメモリアドレス』になります。」と書いた通り、全くの無関係ということはなく、むしろ縁の深い存在です。ですが、「一緒のもの」と考えてしまうと色々な弊害があります。 なので、「C言語がアドレスをどのようなものと位置付けているか」と「機械語上のメモリアドレス」を分けて考えましょう、ということです。
rubato6809

2021/09/10 03:32

「はい。違います」・・・驚き 「これはC言語上の概念であって、「コンピュータ上のメモリアドレスを指定してメモリを書き換えられます」と言ってるわけではない」 これは原理主義の一種でしょうか。質問者が迷わずに書き進められる段階になったらこういう、ある種、抽象的な説明もよいかもしれませんが、基本私はこういう回答に賛成できません。Cで作るプログラムが現実のメモリを使って処理するのに、メモリアドレスを指定してメモリを書き換えているのに、それと違うものを考えろと言われたら初心者は混乱すると思います。 私自身・私の知ってるCプログラマがそうであるように(変数が配置された)メモリそのもの・メモリアドレス・データといった関係をイメージできるのが理解の早道だと思っています。
fana

2021/09/10 04:47 編集

C言語で扱うアドレス値 addr_c から出発して, 物理的な(と言えばいい?)メモリ内のある場所(を指すアドレス値 addr_p)に達するまでに, addr_p = F( addr_c ) 的な何らかの変換Fが(「C言語」の世界の外側で)噛まさっている,くらいに思っとけば良いんじゃない? addr_c と addr_p の値を見比べてみたら全然違うかもしれないし,同じ( F(x)=x )かもしれないけども, C言語(でコードを書く)側からすれば とにかく addr_c が特定の領域を示すことに使えるならばそれで十分. F とか addr_p の実態を知らなくてもやっていける,ってことで.
Zuishin

2021/09/10 05:18 編集

https://stackoverflow.com/questions/15151377/what-exactly-is-a-c-pointer-if-not-a-memory-address/15151496 このあたりの話ですね。 > A pointer value can be some kind of ID or handle or a combination of several IDs (say hello to x86 segments and offsets) and not necessarily a real memory address. 訳: ポインタの示す値は何かの種類の ID やハンドル、またはいくつかの ID を組み合わせたもの(やあ、x86 のセグメントとオフセット)であって、必ずしも実メモリアドレスである必要はない。 例えばセグメントとオフセットが使われている場合、ポインタの値から 1 引くと、値が小さくならず大きくなることがあるため、ポインタの使用には範囲が決められており、その範囲を越えると未定義となります。 これは機械語ではなく C 言語の決まりですね。 環境によってアドレス演算のコードを変えなくて済むよう、C 言語が抽象化して違いを吸収してくれていると考えることができます。
rubato6809

2021/09/10 10:52

私の言葉を裏付けるように、原理主義者の教典?(or経典)の存在まで分かりましたw。念のため:「必ずしも実メモリアドレスである必要はない」・・・メモリアドレスではない、とは言ってないですね。 C言語で扱うポインタの値は(ほぼ)100%メモリアドレスです。 その事はデバッガで確認できます。メモリダンプしてみるのも良いです。 GCCもVSもClangも…、x86の32bitも64bitも、ですから目の前のパソコンはもちろん、ARMも、各種組込みマイコンも、、、C言語プログラムは「コンピュータ上のメモリアドレスを指定してメモリを書き換え」ています。そのようにして処理を進め結果を出します。 将来「F とか addr_p の実態を知らなくてもやっていける」かもしれませんが、今は何か<メモリと違うもの>を想定する必要などありません、むしろメモリを前提にして適切なイメージを作ったほうが良いし、そのほうが手っ取り早く先に進めるでしょう。 今、C言語を学んでいる人、ポインタで躓いてる人には、まず<ポインタの値はメモリアドレス>だということ、変数がメモリ上に配置されること等をベースにして、ポインタのイメージを具体化する事をお勧めします。 例えば変数・各種データのメモリ上の配置(変数やデータの「姿」)を描いてみること。逆に、ポインタや配列、構造体など、データ構造を適切にイメージできないのはマズいです。 私の答えです。 > C言語では機械語などで操作するコンピュータのメモリとは違うということですか? 同じものです。機械語プログラムがメモリを操作するように、C言語プログラムもメモリを操作しています。
Zuishin

2021/09/10 11:18

また、ポインタをインクリメントした場合、アドレスは 1 ではなく 2 や 4 増えることがあります。 機械語ではインクリメントで増えるのは 1 です。
angel_p_57

2021/09/10 13:56

> rubato6809 驚いてる暇があったら基本をちゃんとした方がいいんじゃないですか…? なんですか「原理主義」って。 「多くの場面で機械語としてのメモリアドレスになるけど同一視すると弊害があるからちゃんと分けて考えましょう」と言ってるの、読めてます? 弊害があるの、ご存知ないです?
fana

2021/09/11 02:15 編集

> 将来「F とか addr_p の実態を知らなくてもやっていける」かもしれませんが、今は何か<メモリと違うもの>を想定する必要などありません addr_p をわざわざ「メモリ内のある場所」と述べることによって 「とりあえずメモリを想定した話」を書いたつもりだったのだが… (こまけぇことは今の段階ではまずほっといていいから,今のところは addr_c はメモリのどこかを指すのだと思っとけよ,と.)
rubato6809

2021/09/11 12:21 編集

返信が遅くなりすみません。 angel_p_57さん 基本なら「ポインタの値はメモリアドレス」が基本でしょう。初心者にはまずそこを理解してもらって、今の段階は大枠を掴んでもらうことが大事だと思います。 それに対して、例外的なこと、「弊害がある」こと等は後回しで構わない。その時にまた質問してもらうなり、参考書等を調べてもらうなりすれば良いのだから。 繰り返しも含めて言い足りなかった気持ちを補足します。 ・驚いたコメント「はい。違います」は、まだポインタの正体を掴みかねている人を惑わし混乱させるものだと思います。 ・質問者は機械語プログラムがメモリを操作するイメージを持っており、そこを手がかりにしようとしているのに、「はい。違います」では梯子を外された気持ちになるのではないか。 ・仮想記憶の論理アドレスと物理メモリアドレスの件、質問者の疑問の前提がそこだと確定したのであればその仕組みを説明すれば良いのだけど、確定はしてないのだから、とりあえず脇に置いた方が良いと思います。初心者には余計なことまで言わないほうが良いと思うから。 また、機械語プログラムがメモリを操作するイメージ、仮に実際に動作させたとするなら今どきのOS上で動作させたと思われ、即ちそのメモリアドレスも論理メモリアドレスであるはず。 ・「2つの変数で同じメモリを共有するというのがよくわからない」という疑問は、論理アドレス・物理アドレスのことではない可能性は十分あるので、まずは ozwk さんの回答でよいのではないか。angel_p_57さんの回答は、私にはひっかかりが大きかったので低評価とした次第です。 原理主義・・・イスラム原理主義であればコーランの記述を厳格に守ろうとするあまり時代錯誤で現実にそぐわない規律を人々に科す考え方、というイメージからきています。 fanaさん であれば、その表現を私は「メモリとは違うものを想定すること」と読み違えたようです。すみません。
angel_p_57

2021/09/13 06:10

> 基本なら「ポインタの値はメモリアドレス」が基本でしょう。初心者にはまずそこを理解してもらって、今の段階は大枠を掴んでもらうことが大事だと思います。 それは基本を理解してないだけでしょう。あなたがどの程度理解していようが、理解していなかろうが、私には関係のないことですが、他者の質問・回答にそれで割り込んで情報を錯綜させるのは迷惑です。ということは認識してください。 最近、https://togetter.com/li/1773550 で関連する話をまとめてますので、適宜参考にしてください。 ※この質問の中で話を続ける筋のものではないので、理解できない点があるなら、別途質問をあげてやってください。
退会済みユーザー

退会済みユーザー

2021/09/13 09:11 編集

低評価つけるほど酷い内容の回答とも思えないので、打ち消しの高評価しておきます。
fana

2021/09/13 09:36

ちゃんと低評価理由を書いて欲しいですね. 質問文の日本語が非常にアレなので一体何が「この質問への回答」足り得るのか? というのが謎な状況なので,そのあたりの解釈の違いから来るものなのかもしれないですし. 例えば, > 2つの変数で同じメモリを共有 という話を,単一プログラム内の2つの変数の話であると解釈した場合には, この回答は質問とマッチしていない,と見えるかもしれない.
guest

0

「2つのアプリケーションが同じメモリを割り当てられていたら、
それぞれ勝手に読み書きして問題になるだろう。
2つのポインタ変数が同じアドレスを格納していたら、それぞれ勝手に読み書きしてやっぱり問題だろう。」

ということでしょうか。

であれば、そのとおり、問題あります。
共有したらまずい領域を共有してはいけません。
なんでもかんでも同じアドレスを指すように書いたら当然のごとく誤動作します。

そういうコードを書くときというのは、
共有するという前提でプログラマが注意して書いているから問題ないのです。

投稿2021/09/09 05:49

ozwk

総合スコア13532

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

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだベストアンサーが選ばれていません

会員登録して回答してみよう

アカウントをお持ちの方は

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

ただいまの回答率
85.46%

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

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

質問する

関連した質問