0

hws をグローバルに宣言し、このメソッドでそれを返そうとしましたが、ポインター エラーが発生しました。誰かがその理由を知っていて、解決策を提案できるかどうか疑問に思っていましたか? ランダム化は、乱数を取得するだけです。

extern int hws[100][20];

int randomize()
{

    int value;
    int tru_fals = 0;
    value = -1;
    while ( tru_fals != 1 )
    {
        value = rand();
        if ( 0 < value )
        {
            if( 101 > value )
            {
                tru_fals = 1;
            }
        }
    }
    return value;

}
int *populate()
{

    int i, j;

    i = 0;
    j = 0;
    while( i < 20 )
    {
        while ( j < 100)
        {
            int temp = randomize();
            hws[i][j] = temp;
            j++;
        }
        i++;
    }
    return hws;

}
4

5 に答える 5

2

を定義しますextern int hws[100][20];
これは配列を作成しません。プログラムのどこかにあるはずだと言っているだけです。

それを機能させるには、他のソースファイルで実際に配列を定義する必要があります - int hws[100][20];(なしextern)。次に、両方をコンパイルしてリンクすると、動作するはずです。

ソース ファイルが 1 つだけ必要な場合は、はるかに簡単です。削除するだけexternです。

しかし、実際に問題の本当の原因であるSerge's answerに気付きました。

于 2012-09-20T18:38:16.727 に答える
2

there is a bug: the array is declared as 100x20 but then you iterate through it like it is 20x100.

于 2012-09-20T18:40:45.097 に答える
1

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

の行return hws;populate、式の型hwsは「100 要素の配列の 20 要素の配列int」です。上記の規則により、「の 20 要素配列へのポインタint」、または型に変換されますint (*)[20]。したがって、の正しい宣言は次のようにpopulateする必要があります

int (*populate())[20]
{
   ...
   return hws;
}

次のように読み取ります

      populate           -- populate
      populate()         -- is a function
     *populate()         -- returning a pointer
    (*populate())[20]    -- to a 20-element array
int (*populate())[20]    -- of int.

int (*)[20]また、結果を返すもののタイプも同様である必要があります。

そうは言っても...

このようにグローバル変数を使用することは、いくつかの理由から強くお勧めできません。populate次のように、配列をパラメーターとして渡す方がよいでしょう。

void populate(int (*arr)[20], size_t rows)
{  
  size_t i, j;

  for (i = 0; i < rows; i++)
  {
    for (j = 0; j < 20; j++)
    {
      arr[i][j] = randomize();
    }
  }
}

これを単に次のように呼び出します

populate(hws, sizeof hws / sizeof hws[0]);

可変長配列をサポートするコンパイラ (C99 コンパイラまたは__STDC_NO_VLA__それを定義しないか 0 に定義する C2011 コンパイラ) を使用している場合は、関数を次のように定義できます。

void populate(size_t cols, size_t rows, int (*arr)[cols]) // cols must be declared
{                                                         // before it can be used
  size_t i, j;                                            // to declare arr

  for (i = 0; i < rows; i++)
  {
    for (j = 0; j < cols; j++)
    {
      arr[i][j] = randomize();
    }
  }
}

そしてそれを次のように呼び出します

size_t rows = sizeof hws[0] / sizeof hws[0][0];  // dividing the size of the array
size_t cols = sizeof hws / sizeof hws[0];        // by the size of the first element
populate(cols, rows, hws);                       // gives the number of elements

そのため、20 をどこにもハードコーディングしていません。

可変長配列をサポートするコンパイラを使用しておらず、関数プロトタイプの行数をハードコーディングしたくない場合は、次のようにすることができます。

void populate(int *arr, size_t rows, size_t cols)
{
  size_t i, j;
  for (i = 0; i < rows; i++)
  {
    for (j = 0; j < cols; j++)
    {
      arr[i * rows + j] = randomize();
    }
  }
}

そしてそれを次のように呼び出します

// rows and cols calculated as above
populate(&hws[0][0], rows, cols);

この場合、配列へのポインターを渡す代わりに、最初の要素へのポインターを渡します (アドレス値は同じですが、型はint *の代わりになりint (*)[20]ます。したがって、populate関数はそれを 1D 配列のように扱い、オフセットを計算しますこのトリックは、連続して割り当てられた 2D 配列に対してのみ機能することに注意しi * rows + jてください。

populateこれは、Nx20 だけでなく、任意のサイズの配列で動作できること も意味します。

于 2012-09-20T18:59:52.720 に答える
0

hws は行列です。つまり、それと int **

int * を返しているため、ポインターの型が一致していません。

于 2012-09-20T18:36:30.550 に答える
0

まず、グローバルであるため、返す必要はありません。2 つ目は、int へのポインターへのポインターです。配列の配列です。

于 2012-09-20T18:38:34.587 に答える