9

私はこれを試しましたが、うまくいきません:

#include <stdio.h>

    int * retArr()
    {
    int a[3][3] = {{1,2,3},{4,5,6},{7,8,9}};
    return a;
    }

    int main()
    {
    int a[3][3] = retArr();
    return 0;
    }

次のエラーが表示されます。

エラー 3 エラー C2075: 'a': 配列の初期化には中かっこが必要
です 4 IntelliSense: 戻り値の型が関数の型と一致しません

私は何を間違っていますか?

4

7 に答える 7

8

構造体は 1 つのアプローチです。

struct t_thing { int a[3][3]; };

次に、構造体を値で返します。

完全な例:

struct t_thing {
    int a[3][3];
};

struct t_thing retArr() {
    struct t_thing thing = {
        {
            {1, 2, 3},
            {4, 5, 6},
            {7, 8, 9}
        }
    };

    return thing;
}

int main(int argc, const char* argv[]) {
    struct t_thing thing = retArr();
    ...
    return 0;
}

あなたが直面する典型的な問題はint a[3][3] = {{1,2,3},{4,5,6},{7,8,9}};、あなたの例では、関数が戻った後に回収されるメモリを参照していることです。つまり、呼び出し元が読み取るのは安全ではありません (未定義の動作)。

他のアプローチには、(呼び出し元が所有する) 配列をパラメーターとして関数に渡すか、新しい割り当てを作成する (例: を使用malloc) ことが含まれます。構造体は多くの落とし穴を排除できるので優れていますが、すべてのシナリオに最適というわけではありません。構造体のサイズが一定でない場合や非常に大きい場合は、値による構造体の使用を避けます。

于 2012-11-15T02:11:38.593 に答える
2

いくつかの問題:

まず第一に、関数呼び出しから配列を初期化することはできません。言語定義は単にそれを許可していません。の配列はchar、次のような文字列リテラルで初期化できます。

char foo[] = "This is a test";

wchar_tchar16_t、またはの配列は、char32_tワイド文字列リテラルで初期化できますが、それ以外の場合、初期化子は中括弧で囲まれた値のリストでなければなりません。

次に、タイプの不一致があります。sizeofまたは 単項演算子のオペランドである場合、または宣言で別の配列を初期化するために使用される文字列リテラルである場合を除いて&、タイプ「N 要素配列T」の式は、タイプ「ポインター」の式に変換されますT。 、式の値は最初の要素のアドレスになります。

関数retArrでは、式の の型aは「の 3 要素配列の 3 要素配列int」です。int上記の規則により、これは「の 3 要素配列へのポインタ」型の式に変換されますint (*)[3]

int (*retArr())[3]
{
  int a[3][3] = ...;
  return a;
}

しかし、ブレンダンが指摘するように、かつてのretArr出口aはもはや存在しません。返されるポインター値は無効になります。

于 2012-11-15T02:32:45.687 に答える
-1
#include <stdio.h>

int** retArr()
{
    static int a[3][3] = {{1,2,3},{4,5,6},{7,8,9}};
    return a;
}

int main()
{
    int** a = retArr();
    return 0;
}

返される変数を静的として指定することもできます。また、変数 a を main で int** として宣言する必要があります (次元は指定しないでください)。

于 2012-11-15T02:20:07.247 に答える
-1

OPの例では、配列をスタックに置くのが最も簡単です。私はこれをテストしませんでしたが、次のようになります。

#include stdio.h

void retArr(a[][3]) {
  a[0][0] = 1; a[0][1] = 2; a[0][2] = 3;
  a[1][0] = 4; a[1][1] = 5; a[1][2] = 6;
  a[2][0] = 7; a[2][1] = 8; a[2][2] = 9;
}

main() {
  int a[3][3];
  retArr(a);
}

ええ、これは return 関数で配列を「返す」わけではありませんが、それは質問の意図ではなかったと思います。配列 a[][] はロードされ、ロードされた a[][] は retArr() が呼び出された後に main で使用可能になり、何も上書きされません。

于 2019-04-30T22:56:00.610 に答える
-2

このため:

int * retArr() {
    int a[3][3] = {{1,2,3},{4,5,6},{7,8,9}};
    return a;
}

配列にはローカル スコープがあり、関数を終了するとすぐに破棄されます。これは、 がreturn a;実際にダングリング ポインターを返すことを意味します。

これを修正するには、配列をグローバル スコープに配置するかmalloc()、配列を使用して割り当てられた領域にコピーします。

于 2012-11-15T02:11:02.543 に答える
-5

int**ではなく、返す必要がありintます。

于 2012-11-15T02:06:51.133 に答える