0

実行可能ファイルにコンパイルしたい 2 つの .c ファイルがあります。C の学習を始めたばかりなので、関数間の引数としてテキストを転送する方法を理解するのは難しいと思います (これは、他のすべての言語では信じられないほど簡単であることがわかりました)。

以下に 2 つのファイルを示します。

Program.c

#include <stdio.h>
#include <string.h>

int main(){

char temp[40] = stringCall();
printf("%s",temp);

}

StringReturn.c

#include <stdio.h>
#include <string.h>

char[] stringCall(){

char toReturn[40] = "Hello, Stack Overflow!";
return toReturn;

}

通常、「セグメンテーションに失敗しました (コア ダンプ)」などの問題が発生します。私は多くのグーグルを行ってきましたが、本当に解決策を見つけることができず、「これは関数間でテキストを移動する方法です」という簡単なチュートリアルはありません。

どんな助けでも大歓迎です:)

4

2 に答える 2

2
char toReturn[40] = "Hello, Stack Overflow!";
return toReturn;

これは無効です。関数が返された後にスコープ外になる自動配列を返しています。これにより、未定義の動作が呼び出されます。文字列リテラル自体を返してみてください (プログラム全体で有効です):

return "Hello, Stack Overflow!";

または、配列の動的複製:

char toReturn[40] = "Hello, Stack Overflow!";
return strdup(toReturn);

この後者の場合、free()呼び出し元関数で文字列が必要になります。

于 2012-09-19T17:01:09.483 に答える
1

C では文字列を値として扱うことができないため、これは C では単純ではありません。

これを行う最も柔軟な方法は次のとおりです。

// Program.c
char temp[40];
if (stringCall(temp, sizeof temp) <= sizeof temp) {
    puts(temp);
} else {
    // error-handling
    puts("My buffer wasn't big enough");
}

// StringReturn.c
int stringCall(char *buf, int size) {
    const char toReturn[] = "Hello, Stack Overflow!";
    if (sizeof toReturn <= size) {
        strcpy(buf, toReturn);
    }
    return sizeof toReturn;
}
  • stringCall文字列データを返さず、呼び出し元が提供するバッファに書き込みます
  • バッファには常にサイズが付属しています。ではなくsize_torを使用できます。ssize_tint
  • stringCall書き込み前にサイズを確認します。単一の呼び出しでこれを行う方法は他にもありますが、それらはすべて C89 および C99 にないか、他の方法で欠陥があります。C11が紹介しstrcpy_sます。上記のコードのように、自分でチェックすることと論理的に同等である必要があるツールを使用してください。すべての C 文字列の末尾に見えないように潜んでいる nul ターミネータ用のスペースがあることを確認することを決して忘れないでください。
  • stringCall何も書き込まない場合でも、書き込みたいバイト数を返します。これは、バッファーが小さすぎる呼び出し元が、より大きなバッファーを割り当てて再試行できることを意味します。そのため、呼び出し元はstringCall(NULL, 0)、特定のバッファーを試行せずにサイズを取得できます。
  • ここで使用しsizeofているのは、コンパイラによってサイズがわかっている配列を使用しているためですが、実際には、書き込みたいデータの量を知るために、または他の方法をstringCall使用する可能性があります。strlen
  • 私が書いたように、呼び出し元は に負の値を渡してはいけませんsize。実際にはバッファが負のサイズを持つことはできないため、通常は問題ありません。しかし、本当に確実にしたい場合、または呼び出し元がそれらのバグをキャッチできるようにしたい場合は、if ((int) sizeof toReturn < size)or if (size > 0 && sizeof toReturn < size).

「最も柔軟」が常に最適であるとは限りませんが、関数が実際にオンザフライでテキストを生成している場合、特に呼び出し元が作業の半分を行わずに事前に長さを知る簡単な方法がない場合に適しています。stringCall彼らのためにすることになっています。インターフェイスは C99 標準関数に似ていますsnprintf

于 2012-09-19T17:18:14.230 に答える