1

重複の可能性:
C++ で配列を使用するにはどうすればよいですか?

関数パラメーターとしての 1 次元配列:

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

int func(int a[], int n)
{
    int i;
    for(i = 0; i < n; i++)
        printf("%d ", a[i][j]);
}

int main(void)
{   
    int a[2] = {1,2};
    func(a, 2);
}

正しくコンパイルおよび実行されます。

ただし、関数パラメーターとして 2 次元配列を使用する場合:

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

int func(int a[][], int n)
{
    int i, j;
    for(i = 0; i < n; i++)
        for(j = 0 ; j < n; j++)
            printf("%d ", a[i][j]);
        printf("\n");
}

int main(void)
{   
    int a[2][2] = {{1,2}, {3,4}};
    func(a, 2);
}

正しくコンパイルできません。次のようにコードを変更する必要があります。

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

int func(int a[][2], int n)
{
    int i, j;
    for(i = 0; i < n; i++)
        for(j = 0 ; j < n; j++)
            printf("%d ", a[i][j]);
        printf("\n");
}

int main(void)
{   
    int a[2][2] = {{1,2}, {3,4}};
    func(a, 2);
}

何故かはわからない?誰でもそれがどのように機能するか説明できますか? どうもありがとう。

4

5 に答える 5

7

c の配列 (1 次元と多次元の両方) は、連続したメモリ ブロックに常駐します。これは、 を定義するchar a[3]と、配列が次のようにメモリに配置されることを意味します (私のひどいアスキー アート スキルを許してください)。

| a[0] | a[1] | a[2] |

2 次元配列char a[2][3]の場合、レイアウトは次のようになります。

| a[0][0] | a[0][1] | a[0][2] | a[1][0] | a[1][1] | a[1][2] |  
                              ^
                              +--- first row ends here

したがって、2 次元配列にインデックスを付けるa[i][j]と、コンパイラは次のようなコードを生成します。

*(a + i*3 + j)

これは、「i 行をスキップして、その行のセル j を取得する」と読むことができます。これを行うには、コンパイラは行の長さ (2 番目の次元) を認識している必要があります。これは、2 番目の次元が型定義の一部であることを意味します!

そのため、2 次元配列を関数に渡したい場合は、型定義に必要な次元を指定する必要があります。

于 2013-01-01T14:26:40.743 に答える
3

最近の (例: C2011、およびおそらくC99 ) C標準では可変長配列が有効になっているため、次の関数が機能します。

int
sum (int n, int t[n][n])
{
  int s = 0;
  for (int i = 0; i < n; i++)
    for (int j = 0; j < n; j++)
      s += t[i][j];
  return s;
}   

これは警告なしでコンパイルされgcc-4.7 -std=gnu99 -Wall -O -c ex.c、生成されたアセンブラは期待どおりです

なぜint t[][]機能しないのかというと、全体の各要素が不確定なサイズtの型になるためです。int []

于 2013-01-01T14:22:21.310 に答える
0

これは非常に良い説明です: http://www.eskimo.com/~scs/cclass/int/sx9a.html

于 2013-01-01T14:21:37.707 に答える
0

配列の 2 番目の次元がないと、コンパイラはそれにインデックスを付ける方法を知りません。これは、コンパイラがポインターを使用して何らかの演算を行い、メモリ内の値を見つける場所を特定するためです。

于 2013-01-01T14:21:41.567 に答える
0

C の配列は非常に「弱く」、通常は実行時に最初の要素へのポインターだけで表されます。のようなものを宣言するとint a[][]、各要素のアドレスを計算する方法を知ることはできません。型が無効であるため、これがコンパイルされない理由です。

を持っていて、またはint a[][]を渡して呼び出すことができた場合、関数内のコードがこれらの異なる配列の適切なアドレス計算に魔法のように「適応」する方法はありません。これがうまくいかない理由です。int big[8][8]int small[2][2]

のような一般的関数を記述し、手動でアドレス計算を行うことができint *matrix, size_t widthます。matrix[i][j]matrix[i * width + j]

于 2013-01-01T14:21:57.737 に答える