0

2D 配列の 2 つの要素を交換する関数を作成しようとしています。

void swap(int surface[][], int x1, int y1, int x2, int y2) {
    int temp = surface[x1][y1];
    surface[x1][y1] = surface[x2][y2];
    surface[x2][y2] = temp;
}

ただし、コンパイル(gcc)しようとすると、次のエラーメッセージが表示されます。

Sim_Annealing.c: In function `swap': 
Sim_Annealing.c:7: error: invalid use of array with unspecified bounds
Sim_Annealing.c:8: error: invalid use of array with unspecified bounds
Sim_Annealing.c:8: error: invalid use of array with unspecified bounds
Sim_Annealing.c:9: error: invalid use of array with unspecified bounds

2D 配列を関数パラメーターとして使用するために必要な特別な魔法はありますか?

ご協力いただきありがとうございます。関数パラメーターとしての配列の適切な参照を知っている場合は、それらを私の方法で送信してください:)

4

5 に答える 5

6

配列パラメータを宣言するだけです。さらに良いことに、初期宣言と関数の仮パラメーターの両方に typedef を使用します。

問題は、行のサイズ、つまり列の数がわからないと、後続の行を取得するためのポインター調整を計算する方法がないことです。興味深いことに、行数を知る必要はありません。

たとえば、これは機能します:

void swap(int surface[][20], int x1, int y1, int x2, int y2) {
  int temp = surface[x1][y1];
    surface[x1][y1] = surface[x2][y2];
    surface[x2][y2] = temp;
}

ただし、呼び出し元の型と関数の型を結び付ける方がよいでしょう。


すべての添え字アクセスには乗算が必要ですが、これは機能します (C99 準拠のコンパイラのみ) ...

int f(int, int, int a[*][*]);

int f(int r, int c, int a[r][c])
{
  return a[99][100];
}

C89 以前の環境でも機能する別の例:

typedef int surface_t[][20];

surface_t therealthing = {
  { 1, 2, 3},
  { 4, 5, 6}
};

void swap(surface_t x) {
  x[0][2] = 'q';
}

void f1(void) {
  swap(therealthing);
}

そして最後に、可変長配列はごく最近のものであるため、伝統的で今でも最速の手法は を渡すことint *a[]です。これには、行または列の長さの知識は必要ありませんが、ポインター ベクトルを構築する必要があります。

于 2009-09-30T23:40:03.877 に答える
1

GCC では、可変長配列を関数の引数として使用できます。

#include <stdio.h> 

void swap(int size; int surface[][size], int size, int x1, int y1, int x2, int y2) {
  int temp = surface[x1][y1];
  surface[x1][y1] = surface[x2][y2];
  surface[x2][y2] = temp;
}

int s[10][10];

int main(){
  s[1][1] = 11;
  s[2][2] = 22;

  printf("s[1][1]: %i   s[2][2]: %i\n", s[1][1], s[2][2] );
  swap( s, 10, 1, 1, 2, 2 );
  printf("s[1][1]: %i   s[2][2]: %i\n", s[1][1], s[2][2] );

  return 0;
}
于 2009-10-01T00:50:56.293 に答える
1

配列が「実際の」2D 配列である場合、最初の次元以外のすべてのサイズを指定する必要があります。

void swap(int surface[][NUMBER_OF_COLUMNS], int x1, int y1, int x2, int y2) {
    ...
}

これにはいくつかの潜在的な問題があります。2D 配列が実際にはポインターの配列 ( ) である場合、それは機能せず、パラメーターをポインターへのポインターにint *surface[]変更する必要があります。surface

void swap(int **surface, int x1, int y1, int x2, int y2) {
    ...
}

または、関数をより一般的なものにするために、2 つの int ポインター (どこでも指すことができる) を受け入れるように変更して、それらを交換することができます。

void swap(int *a, int *b) {
    int temp = *a;
    *a = *b;
    *b = temp;
}

次のように呼び出します。

swap(&surface[x1][y1], &surface[x2][y2]);
于 2009-09-30T23:47:13.910 に答える
1

C では、オフセットの計算方法を知る必要があるため、配列の最初の次元のみを未指定のままにすることができます。可変サイズの 2D 配列で作業する必要がある場合は、配列を int* として渡し、2 番目の次元のサイズを渡し、自分でポインター演算に渡します。

void swap(int *surface, int ySize, int x1, int y1, int x2, int y2) {
    int temp = *(surface + ySize * x1 + y1) ;
    *(surface + ySize * x1 + y1) = *(surface + ySize * x2 + y2);
    *(surface + ySize * x2 + y2) = temp;
}

これは、[][] 構文が行っていることと同じです。C の配列は実際には単なるポインターであるためです。

于 2009-09-30T23:48:59.537 に答える