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

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

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

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

Q&A

解決済

3回答

1142閲覧

某SNSで見つけたコードとc++での参照について

moomoomoo

総合スコア3

C++

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

0グッド

0クリップ

投稿2021/05/09 15:30

某SNSで以下のrandomIntのような記述を見かけたのですが,この関数の意図が全く分かりません.ネタとして投稿したものなのかもしれませんが,以下のコードを実行したら0が表示されました.
また,main文の中にint& b = aを追記したら,大体32500~32800が実行されるたびにランダムで表示されるようになりました.
もう全く理解できないです.

ramdomIntの意図と,参照することで値が変わる理由は何なのでしょうか?
これが分からないと困るわけではないですが,もやもやするので教えていただけるとありがたいです.

#include<stdio.h> int randomInt() { int n; return n; } int main() { int a; a = randomInt(); printf("a = %d\n", a); }

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

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

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

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

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

ppaul

2021/05/09 17:37

int& b = aを追記したら はどこに追記したのでしょうか? 何カ所かに入れてみたのですが再現しません。
moomoomoo

2021/05/09 21:51 編集

下記のようにしたらなりました. a = randomInt();の下に書いても同じ結果になりました. int main() { int a; int& b = a; a = randomInt(); printf("a = %d\n", a); }
ppaul

2021/05/09 23:25

g++ (GCC) 4.8.5 20150623 (Red Hat 4.8.5-44) では再現しませんでした。常に0が印字されます。 使っているコンパイラを教えてください。 たいていのC++処理系の動作原理から考えると、このような変数宣言を行ってた場合には、randomIntの値は変わらないはずですので不思議ですね。
moomoomoo

2021/05/10 04:18

wsl ubuntu18.04のg++7.5です
FKD

2021/05/11 01:40

ASLRの有無とかですかね?
FKD

2021/05/11 01:49 編集

ググってみた所、元SNS?っぽいところでもASLR有効な場合と書いてありました。 面白いアイデアですね。(使ってはいけないけどw)
退会済みユーザー

退会済みユーザー

2021/05/12 01:49 編集

いくつか回答ついてるので、それに対するコメントくらいはしたらどうですか?放置はNGです。 解決したならベストアンサーを選択し、解決に至っていないならその理由を追記してください。
moomoomoo

2021/05/13 22:57 編集

返信が遅れました.申し訳ないです. 正直参照についてはあまり納得がいってないのですが,randomIntの挙動についてはおかげさまで理解しました. 皆さんご回答ありがとうございました.
guest

回答3

0

ベストアンサー

コンパイラや最適化レベルによって未初期化の変数を出力する場合もあるし、0を出力する場合もあるし、関数呼び出しそのものが無かった事になる場合もあります。どういう結果になるか予想がつかないだけで、乱数でも何でもありません。
適切な実装の乱数出力関数を使用してください。

下記は、オンラインのコンパイラで出力したアセンブリコードと実行結果です。

【x86-64 clang 12.0.0 (最適化無し)】 randomInt: # @randomInt push rbp mov rbp, rsp mov eax, dword ptr [rbp - 4] pop rbp ret main: # @main push rbp mov rbp, rsp sub rsp, 16 call randomInt mov dword ptr [rbp - 4], eax mov esi, dword ptr [rbp - 4] movabs rdi, offset .L.str mov al, 0 call printf xor eax, eax add rsp, 16 pop rbp ret .L.str: .asciz "a = %d\n" --------------------- Program returned: 0 Program stdout a = 0
【x86-64 clang 12.0.0 (最適化-O2)】 randomInt: # @randomInt ret main: # @main push rax mov edi, offset .L.str xor eax, eax call printf xor eax, eax pop rcx ret .L.str: .asciz "a = %d\n" --------------------- Program returned: 0 Program stdout a = -1294604376

投稿2021/05/10 01:04

退会済みユーザー

退会済みユーザー

総合スコア0

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

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

0

実行環境や、コード内容にもよりますが、ローカル変数はスタック上に確保されることが多いです。
int n; は初期化されていないので、関数呼び出し時のスタックの状態によって値が変化します
「C言語 関数フレーム」とかで調べると関数呼び出し時のスタックの使用状況が理解できると思います。

例えば下のように書くと、出力を 999 固定に出来ます
これは func()呼び出しによって int n; が対応するスタックの値を事前に 999 で書き換えているからです
ただし実行環境によって結果は変わるので注意
WSL2 Ubuntu 20.04LTS, gcc 9.3.0だと999が出ます

c

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

投稿2021/05/09 15:36

編集2021/05/09 15:38
jamjam3

総合スコア165

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

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

0

ローカル変数は初期化されません。
たまたまその場所にあった値が読めるだけのはなしです。
たいていローカル変数はスタック上に取られるので、その値が読み込まれます

投稿2021/05/09 15:34

y_waiwai

総合スコア88051

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

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

yumetodo

2021/05/09 17:27

まあつまりは未定義動作
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.35%

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

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

質問する

関連した質問