アカウント名:
パスワード:
私なりにこの問題点を説明させていただきます。間違っていたらごめんなさい。結論から言うとメモリ領域を本来の意味から逸脱した状態で使っている瞬間があるからだと考えています。
スタックは下に向かって伸びていくとしますので、スタックポインタより上が使用中、下が未使用と考えてください。
1.addressee()に入った時にresultはスタック上に確保され初期化される。
+--------------+|return address|←addressee()を呼び出した場所への戻り+--------------+|<-result || a[world\0] |+--------------+←スタックポインタ
2.addressee()で使った領域を破棄し呼び出し元に戻る。
コメント付いているのに気付いてませんでした。
その説明は誤りだと思います。2. の時点で既に領域が無効だ、という説明かと思いますが、その場合、同様の議論が struct ではなく int に対しても成立し以下のコードも誤りとなってしまいます(3. で持ってくるのはアドレスではなく値になりますが領域自体が無効なら議論は同じです)。
int addressee(void) { int result = 5; return result;} int main(void) { printf("Hello, %d!\n", addressee()); return 0;}
さすがにこのコードが誤りだと関数の戻り値は全て使えないことになってしまいます。確かに result は関数内で確保されていますが値返しで返ってくるため再度スタック上に積まれて呼び出し側でも有効な状態で返ってきます。問題はそのスタック上の値がいつまで有効か、です。C99 規格上では次の副作用完了点まで有効ですので以下のコードは未定義動作を含みません(次の副作用完了点は printf 呼び出しなのでその前に a[0] の評価は完了する)。嫌な例でわざわざ f() 呼び出しが入っているのは別の副作用完了点を入れて問題を起こすため、です。
int main(){ printf("%c%c!\n", addressee().a[0]); return 0;}
より多くのコメントがこの議論にあるかもしれませんが、JavaScriptが有効ではない環境を使用している場合、クラシックなコメントシステム(D1)に設定を変更する必要があります。
目玉の数さえ十分あれば、どんなバグも深刻ではない -- Eric Raymond
単なる使い方の誤りではないですか (スコア:1, すばらしい洞察)
私なりにこの問題点を説明させていただきます。間違っていたらごめんなさい。結論から言うとメモリ領域を本来の意味から逸脱した状態で使っている瞬間があるからだと考えています。
スタックは下に向かって伸びていくとしますので、スタックポインタより上が使用中、下が未使用と考えてください。
1.addressee()に入った時にresultはスタック上に確保され初期化される。
2.addressee()で使った領域を破棄し呼び出し元に戻る。
Re:単なる使い方の誤りではないですか (スコア:1)
コメント付いているのに気付いてませんでした。
その説明は誤りだと思います。2. の時点で既に領域が無効だ、という説明かと思いますが、その場合、同様の議論が struct ではなく int に対しても成立し以下のコードも誤りとなってしまいます(3. で持ってくるのはアドレスではなく値になりますが領域自体が無効なら議論は同じです)。
さすがにこのコードが誤りだと関数の戻り値は全て使えないことになってしまいます。確かに result は関数内で確保されていますが値返しで返ってくるため再度スタック上に積まれて呼び出し側でも有効な状態で返ってきます。問題はそのスタック上の値がいつまで有効か、です。C99 規格上では次の副作用完了点まで有効ですので以下のコードは未定義動作を含みません(次の副作用完了点は printf 呼び出しなのでその前に a[0] の評価は完了する)。嫌な例でわざわざ f() 呼び出しが入っているのは別の副作用完了点を入れて問題を起こすため、です。