かなり基礎的な質問になるのですが、疑問に思うことがあり、質問をさせていただきます。
関数内で宣言した変数を戻り値として使う場合ですが、ポインタなどではなく実体の場合でも、静的変数として宣言をしたほうが良いのでしょうか?
現実的に考えると、プログラムが関数から出て、呼び出した側の関数が戻り値を受け取るまでの瞬間に、その領域が書き換えられる可能性は極めて低いと思うのですけど、C言語の仕様としてはどうなのでしょうか?
関数内で宣言した戻り値に使う変数には、必ずstaticをつけた方が良いのでしょうか?
もしおわかりでしたら教えて下さい。
No.7ベストアンサー
- 回答日時:
> ちょっと難しく考えすぎちゃっていました。
いえ、とてもよい感覚をお持ちだと思います。
恐らく、「呼び出し元が戻り値を受ける前に、返したいローカル変数が消滅してしまうのではないか」という懸念をお持ちなのではないでしょうか。
だとすれば、お察しの通りです。
おそらく、多くのC言語およびC++言語のコンパイラは、そのようなコードを生成するでしょう。
けれど、安心してください。
そのようなコンパイラであったとしても、戻り値は暗黙的に一時変数に待避されていますので、呼び出し元は戻り値を安全に受けることができます。
つまり、static にする必要はありません。
ただ、一時変数にコピーされるということは、無駄なコピーが1回働くということを意味します。
ですので、大きな構造体などを戻り値に指定するのは避けたほうがよいでしょう。
大きな構造体を返したい場合は、構造体のポインタを引数で受け取るように心がけてください。
目安として、アドレスより大きな構造体は返さないことです。
そうなんです。
>呼び出し元が戻り値を受ける前に、返したいローカル変数が消滅してしまうのではないか
と、考えてしまっていたんです。
もしくは消滅はしないまでも、他の変数などに使われてしまう可能性が絶対にないとはいえないのではないかと・・・
でも、一時変数にコピーされるのなら大丈夫なんですね。
しかも、戻り値に構造体を使わないほうが良い理由というのが初めてきちんとわかりました(^_^;)
ご返答、ありがとうございます。
No.8
- 回答日時:
> 現実的に考えると、プログラムが関数から出て、呼び出した側の関数が戻り値を受け取るまでの瞬間に、その領域が書き換えられる可能性は極めて低いと思うのですけど、C言語の仕様としてはどうなのでしょうか?
この問題はマルチスレッドにしない限り起りません。
(厳密には他にもあると思いますが)
> 関数内で宣言した戻り値に使う変数には、必ずstaticをつけた方が良いのでしょうか?
基本的にする必要はないと思いますが、
ケースバイケースだと思います。
個人的に必要がある思うケースは、
ある関数とあるデータの関係を密接にしたい場合は必要だと思います。
staticの変数を返す関数ではないですが
string.h にある、strtokとstrtok_rの違いについて考えてみてください。
strtokは確実に、staticな変数を使っています。
(もしかするとスレッドローカル変数かもしれませんが)
マルチスレッドを考慮に入れていたわけではないので、基本的には心配する必要がないということですね。
いろいろと勉強になりました。
ご返答ありがとうございます。
No.6
- 回答日時:
>関数内で宣言した変数を戻り値として使う場合ですが、ポインタなどではなく実体の場合でも、静的変数として宣言をしたほうが良いのでしょうか?
変数であろうと、ポインタ変数であろうと、
関数内で宣言された自動変数は関数終了時に破棄されます。
関数内で宣言した変数のポインタを返却しそれ以外の関数でも使用する
なら静的変数にする以外にありませんが、戻り値として
C言語では式を持つreturn文を実行すると、その式の"値"を
関数呼び出し式の値として呼び出し側へ返すという決まりがあります。(C99)
つまり
・値を返すならば自動変数で問題ない。
静的変数を返却する場合むしろマルチスレッド環境などでは、
バグになる可能性もある。
・関数内で宣言した自動変数に値を入れ、その変数のポインタを
上位に返し使用する事はできない。
・関数内で宣言した静的変数ならばそのポインタを返却し上位でも
使用することができるが、やはりマルチスレッド環境などでの
考慮は必要。
って感じの事が分かっていれば大丈夫かと。
値を返す場合は、自動変数で問題なかったんですね。
自分でもずっとそのつもりでいて、実際にそのようなソースを書いてきたのですが、自動変数についていろいろ勉強していたら、ふと疑問に感じてしまって(^_^;)
ご返答、ありがとうございました。
No.5
- 回答日時:
マルチスレッド/マルチタスク環境での心配をしておられるのなら,
むしろ戻り値を static 変数に入れる方が問題です.
関数内で変更する変数を static にしてしまうと,
その関数はリエントラントでなくなりますし,
static 変数の排他制御をしないのならスレッドセーフでもなくなります.
リエントラント (Wikipedia)
http://ja.wikipedia.org/wiki/%E3%83%AA%E3%82%A8% …
スレッドセーフ (Wikipedia)
http://ja.wikipedia.org/wiki/%E3%82%B9%E3%83%AC% …
マルチスレッドのことまでを考慮しているわけではなかったんです。というより、そこまで考慮できるほどの熟練者でもないので(^_^;)
新しい用語もたくさん教えていただいたので、これから勉強してみます。
ご返答、ありがとうございました。
No.2
- 回答日時:
>呼び出した側の関数が戻り値を受け取るまでの瞬間に、
>その領域が書き換えられる可能性
マルチスレッドのプログラムですか?
排他制御と static 変数には何の関係もないと思いますが。
変数を static と宣言することによって tadasuke200 さんが期待している効果を補足すると、アドバイスを得やすいでしょう。
マルチスレッドまで考えてのことではないのですが、例えば、free関数などで開放した領域をすぐに使用するとか、基本的には動くけどCの仕様としては間違っているというような状況なのかと考えたりしてしまいまして・・・
難しく考えすぎました(^_^;)
ご返答ありがとうございます。
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
似たような質問が見つかりました
- JavaScript カラーミーショップのsectionループ内で、[引数][戻り値]ありの関数的な処理を行いたいです。 1 2022/05/07 19:39
- 物理学 座標変換に関して質問です。参考書に 「力は一般に時間と場所によって異なるから力f(ベクトル)はx,y 3 2022/07/03 20:24
- C言語・C++・C# スタックフレームの消滅 6 2023/05/20 12:33
- 高校 対数方程式につきまして 4 2022/05/05 07:55
- C言語・C++・C# C言語初心者 ポインタについて、お助けください、、 2 2023/03/15 23:50
- 大学受験 数学が苦手で社会が得意な場合は一橋よりも東大の方が受かりやすい、ということはあり得ますか? 3 2022/04/16 16:46
- JavaScript 変数宣言と初期値代入の場所について 3 2022/10/31 19:09
- 高校 三次関数のグラフにつきまして 3 2022/05/15 11:14
- C言語・C++・C# 競技プログラミングに関する質問です。 3 2022/04/03 19:51
- その他(プログラミング・Web制作) pythonのプログラムについての質問です。 1 2023/05/26 10:31
関連するカテゴリからQ&Aを探す
おすすめ情報
- ・漫画をレンタルでお得に読める!
- ・【大喜利】【投稿~11/22】このサンタクロースは偽物だと気付いた理由とは?
- ・お風呂の温度、何℃にしてますか?
- ・とっておきの「まかない飯」を教えて下さい!
- ・2024年のうちにやっておきたいこと、ここで宣言しませんか?
- ・いけず言葉しりとり
- ・土曜の昼、学校帰りの昼メシの思い出
- ・忘れられない激○○料理
- ・あなたにとってのゴールデンタイムはいつですか?
- ・とっておきの「夜食」教えて下さい
- ・これまでで一番「情けなかったとき」はいつですか?
- ・プリン+醤油=ウニみたいな組み合わせメニューを教えて!
- ・タイムマシーンがあったら、過去と未来どちらに行く?
- ・遅刻の「言い訳」選手権
- ・好きな和訳タイトルを教えてください
- ・うちのカレーにはこれが入ってる!って食材ありますか?
- ・おすすめのモーニング・朝食メニューを教えて!
- ・「覚え間違い」を教えてください!
- ・とっておきの手土産を教えて
- ・「平成」を感じるもの
- ・秘密基地、どこに作った?
- ・【お題】NEW演歌
- ・カンパ〜イ!←最初の1杯目、なに頼む?
- ・一回も披露したことのない豆知識
- ・これ何て呼びますか
- ・初めて自分の家と他人の家が違う、と意識した時
- ・「これはヤバかったな」という遅刻エピソード
- ・これ何て呼びますか Part2
- ・許せない心理テスト
- ・この人頭いいなと思ったエピソード
- ・牛、豚、鶏、どれか一つ食べられなくなるとしたら?
- ・好きなおでんの具材ドラフト会議しましょう
- ・餃子を食べるとき、何をつけますか?
- ・あなたの「必」の書き順を教えてください
- ・ギリギリ行けるお一人様のライン
- ・10代と話して驚いたこと
- ・大人になっても苦手な食べ物、ありますか?
- ・14歳の自分に衝撃の事実を告げてください
- ・家・車以外で、人生で一番奮発した買い物
- ・人生最悪の忘れ物
- ・あなたの習慣について教えてください!!
- ・都道府県穴埋めゲーム
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
セグメントエラー
-
C言語のポインタに直接アドレス...
-
戻り値で構造体を返すことは可...
-
fopne で失敗する原因
-
init関数の意味
-
LPSTR型の初期化について
-
CWnd::EnableWindow()の扱い方
-
ポインタ変数のサイズについて...
-
自作関数の引数
-
自分のIID_IUnKnown取得について
-
c言語のポインタについて初心者...
-
#define NULL ((void *)0) の弊害
-
アプリを32bitから64bit移行
-
Run-Time Check Failure #3とい...
-
C言語習得のレベル.
-
C言語 関数の戻り値と自動変数
-
c言語で任意のファイルから読み...
-
^と*の違いについて
-
別のDLLのダイアログを・・・
-
クラスの参照渡しとメンバ変数...
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
セグメントエラー
-
C言語のポインタに直接アドレス...
-
init関数の意味
-
Run-Time Check Failure #3とい...
-
fopne で失敗する原因
-
戻り値で構造体を返すことは可...
-
LPSTR型の初期化について
-
ExcelVBAでのkernel32(64bit)
-
参照型で受け取った引数をポイ...
-
ハンドル、アドレス、ポインタ...
-
ハンドルはポインタか
-
C言語でのconstを返す関数
-
デバイスハンドルとは?
-
Cで作成したDLL関数をVBから呼...
-
popenした子プロセスのプロセス...
-
c言語で任意のファイルから読み...
-
[excel vba] マウスポインタの...
-
パスからファイル名を抽出
-
プーさんのマウスポインタを教...
-
基本アルゴリズムの『返す』の...
おすすめ情報