2016-08-09 7 views
3

私は現在、その名前の通り、2つの文字列を連結するルーチンString_concat(char *str1, char *str2)を使用しています。これを行うために、このルーチンはヒープ上にメモリを動的に割り当てます(malloc()経由)。しかし、返された文字列は呼び出し側のルーチンでしか使われていないので、スタックにメモリを直接割り当てることを考えているので(alloca()経由)、String_concat()String_concat2(char* str1, char* str2, char* dest)のように置き換えると、 )を引数として使用します。だから私の質問です:String_concat2()呼び出しルーチンのスタックに書き込むのは大丈夫ですか、または__attribute__((always_inline))経由で強制的にインライン展開する必要がありますか?サブルーチンが呼び出しルーチンのスタックに書き込むことは安全ですか?

+0

C11ドラフト標準n1570:* 6.2.4保管期間o fオブジェクト2オブジェクトの存続期間は、記憶が であることが保証されているプログラム実行の部分です。オブジェクトが存在し、一定のアドレスを持つ、33)、寿命の間に最後に格納された値が のままです。 34)オブジェクトが寿命( )の外に参照された場合、動作は未定義です。 オブジェクトが指すオブジェクト(またはその直前のオブジェクト)がその存続期間の終わりに達すると、ポインタの値は不定になります* – EOF

+2

この関数を使用して*使用されていない*文字列を作成する場合は、呼び出し関数では、何ですか?これは、単に不要であるか、または非常に未来のものである早期最適化の場合のようです。 –

+0

パフォーマンス上の理由からこれを実行しますか?これはルーチン間の本当に強い結合のように見えるので、これはほとんど常に悪いことだと思います... –

答えて

5

関数がその呼び出し関数のスタックフレームに書き込むのに問題はありません。例えば

:上記のコードで

void foo(int *ptr) { 
    *ptr = 7; 
} 

void bar(void) { 
    int value; 
    foo(&value); 
} 

foo機能は、それを呼び出すbar関数のスタックフレームにある場所に書き込んでいます。

+0

明らかに、なぜ私はそれを考えなかったのですか?ありがとう! –

3

呼び出し先ルーチンは、常に呼び出し元の値を変更できます。しかし、アセンブリ言語を使用してコンパイラを模倣しない限り、は、独自の変数が既に存在するため、スペースを呼び出し元スタックに割り当てます。

あなたが呼び出し側に配列を返すために必要がある場合、2つだけのポータブルな方法は次のとおりです。

  • 呼び出し先は、malloc関数でメモリを割り当て、呼び出し元にそのアドレスを渡す - 呼び出し側が、後にメモリブロックを解放します
  • 発信者事前割り当てメモリと呼び出し先にバッファを渡す - 呼び出し先のみバッファを充填し、それが全く割り当てられているかどうかではない割り当てされる心配しない(静的または自動ストレージかもしれない)
関連する問題