2016-12-21 7 views
0

1バイト要素の動的サイズマトリックスを作成しようとしています。そうするために、私は次の関数を定義しました。問題は、行列の最初の "nrows"要素を対応する行を指すように設定しようとするときです(行列[i] [j]を行うことができます)。 matrix[i] = matrix[nrows + i * single_row_elements_bytes];が十分に機能しないようです(プログラムはコンパイルされますが、コアセグメント違反エラーがスローされます)。どうすればこの作品を作れますか?ダイナミックマトリックス上にポインタを設定する

uint8_t **NewMatrix(unsigned nrows, unsigned ncols) 
{ 

    uint8_t **matrix; 
    size_t row_pointer_bytes = nrows * sizeof *matrix; 
    size_t single_row_elements_bytes = ncols * sizeof **matrix; 

    matrix = malloc(row_pointer_bytes + nrows * single_row_elements_bytes); 

    unsigned i; 

    for(i = 0; i < nrows; i++) 
     matrix[i] = matrix[nrows + i * single_row_elements_bytes]; 

    return matrix; 
} 
+0

'matrix [i]'のスペースを割り当てる必要があります。 – RoadRunner

+0

@RoadRunnerは、その領域がすでにmallocによって割り当てられています。私は行列[nrows + i ...]が指す値と同じになるようにポインタを設定しようとしています。 –

+0

@ C.P.私は以下の答えを書いた。 – RoadRunner

答えて

0

、あなたは2次元配列を割り当てています間違って実際には、2D配列を割り当てずに、断片的なルックアップテーブルを割り当てることになります。

2D配列を動的に割り当てる正しい方法は、How do I correctly set up, access, and free a multidimensional array in C?に記載されています。これがどのように動作し、配列ポインタがどのように機能するかについての詳細な説明はFunction to dynamically allocate matrixで説明されています。

#include <stdio.h> 
#include <stdint.h> 
#include <stdlib.h> 
#include <inttypes.h> 

void NewMatrix (size_t nrows, size_t ncols, uint8_t (**matrix)[nrows][ncols]) 
{ 
    *matrix = malloc (sizeof (uint8_t[nrows][ncols])); 
} 


int main (void) 
{ 
    size_t r = 3; 
    size_t c = 4; 

    uint8_t (*arr_ptr)[r][c]; 
    NewMatrix(r, c, &arr_ptr); 
    uint8_t (*matrix)[c] = arr_ptr[0]; 

    uint8_t count=0; 
    for(size_t i=0; i<r; i++) 
    { 
    for(size_t j=0; j<c; j++) 
    { 
     matrix[i][j] = count; 
     count++; 
     printf("%2."PRIu8" ", matrix[i][j]); 
    } 
    printf("\n"); 
    } 

    free(arr_ptr); 
} 
+0

なぜunsignedの代わりにsize_tを使用しますか?それがsizeof()の返り値型(そしてmalloc入力の場合)だと思いました –

+0

@ C.P。ちょっとしたことですが、 'size_t'は、配列のサイズを記述するとき、または配列を繰り返し処理するときに使用する最も移植性の高い/正しい型です。配列内で使用されるバイト数を返すために 'sizeof(array)'が必要なので、sizeofは実際に 'sizeof'に関連しているため、' size_t'は常に最大サイズの配列を扱える大きさでなければなりません与えられたシステム。例えば、unsigned intが65535であるが、システムが64kbより大きい配列を許容する16ビットシステムがあるとします。 – Lundin

+0

'size_t'を使用する主な理由はおそらく、標準のライブラリ関数(例えば、' memcpy'や 'strlen')との互換性を保つことです。 – Lundin

0

あなたのコードにはいくつか問題があると思います。

matrix = malloc(row_pointer_bytes + nrows * single_row_elements_bytes); 

へ:

matrix = malloc(row_pointer_bytes); 

行列でuint8_t*多くの行のためのスペースを割り当て

  • あなたはこのラインを簡素化することができます。

    malloc()関数はヒープ上に要求されたメモリを割り当てるために必要なバイトsize_t量を必要とし、それへのポインタを返します。

    これは、マトリックスに必要な行数(この場合はnrows)を単純に割り当てることができます。

  • また、あなたのforループ:各行がnの列を持っているので

    for(i = 0; i < nrows; i++) 
        matrix[i] = matrix[nrows + i * single_row_elements_bytes]; 
    

    は、matrix[i]にメモリを割り当てません、あなたはそれらの列にメモリを割り当てる必要があります。

    これは、代わりに次のようになります。

    for(i = 0; i < nrows; i++) 
        matrix[i] = malloc(single_row_elements_bytes); 
    
  • もう一つの問題は、single_row_elements_bytesを割り当てる方法です。代わりに:

    size_t single_row_elements_bytes = ncols * sizeof **matrix; //**matrix is uint8_t** 
    

    このニーズはn列、ないuint8_t**バイトのためuint8_tバイトを割り当てます。それは代わりに、これをすることができます:

    size_t single_row_elements_bytes = ncols * sizeof(uint8_t); 
    

は次のように書かれている場合、これは、あなたのコードをコンパイルすると発表しました。これは私がコードをテストするために書いた例です。

#include <stdio.h> 
#include <stdlib.h> 
#include <stdint.h> 
#include <inttypes.h> 

uint8_t **NewMatrix(unsigned nrows, unsigned ncols); 

int 
main(int argc, char *argv[]) { 
    uint8_t **returnmatrix; 
    unsigned nrows = 2, ncols = 2; 
    int i, j; 

    returnmatrix = NewMatrix(nrows, ncols); 

    for (i = 0; i < nrows; i++) { 
     for (j = 0; j < ncols; j++) { 
      printf("Enter number for row %d column %d: ", i+1, j+1); 

      /* format speficier for uint8_t, from <inttypes.h> */ 
      if (scanf("%"SCNu8"", &returnmatrix[i][j]) != 1) { 
       printf("Invalid 8 bit number.\n"); 
       exit(EXIT_FAILURE); 
      } 
     } 
    } 

    printf("\nYour matrix:\n"); 
    for (i = 0; i < nrows; i++) { 
     for (j = 0; j < ncols; j++) { 
      printf("%d ", returnmatrix[i][j]); 
     } 
     printf("\n"); 
    } 

    /* Good to free at the end */ 
    free(returnmatrix); 

    return 0; 
} 

uint8_t 
**NewMatrix(unsigned nrows, unsigned ncols) { 
    int i; 
    uint8_t **matrix; 

    size_t row_pointer_bytes = nrows * sizeof * matrix; 
    size_t column_row_elements_bytes = ncols * sizeof(uint8_t); 

    matrix = malloc(row_pointer_bytes); 

    /* Good to check return value */ 
    if (!matrix) { 
     printf("Cannot allocate memory for %d rows.\n", nrows); 
     exit(EXIT_FAILURE); 
    } 

    for(i = 0; i < nrows; i++) { 
     matrix[i] = malloc(column_row_elements_bytes); 
     if (!matrix[i]) { 
      printf("Cannot allocate memory for %d columns.\n", ncols); 
      exit(EXIT_FAILURE); 
     } 
    } 

    return matrix; 
} 

入力:

Enter number for row 1 column 1: 1 
Enter number for row 1 column 2: 2 
Enter number for row 2 column 1: 3 
Enter number for row 2 column 2: 4 

出力:でコンパイル

Your matrix: 
1 2 
3 4 

:別の答えに記載されたさまざまなバグは別に

gcc -Wall -o matrix matrix.c 
0
for (i=0;i<nrows;i++) 
      matrix[i] = (uint8_t *)malloc(ncols * sizeof(uint8_t)); 

2行以下ザは、上記の2行と

for(i = 0; i < nrows; i++) 
      matrix[i] = matrix[nrows + i * single_row_elements_bytes]; 

によって置換されなければならない:ここ

は、特定の場合のために、上述の技術を用いた例であります割当サイズとして(nrows + i * single_row_elements_bytes)を、nrows = 5ncols =5とし、合計で65バイトを割り当てる。 これは、行ポインタ(64ビットポインタサイズを仮定する)を格納するための40バイトと、各r、c要素の内容を格納するための残りの25バイトを含みます。しかし、列ポインタ(その行の各要素へのポインタ)のメモリは割り当てられません。

したがって、逆参照matrix[i][j]は、segフォールトになります。

関連する問題