0

I practice the 2D dynamic array with reference to the URL below: https://thispointer.com/allocating-and-deallocating-2d-arrays-dynamically-in-c-and-c/

My code:

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

int** create_2d_arr(int row_size,int colum_size)
{
    int** array = (int**)malloc(sizeof(int*)*row_size);
    for (int i = 0; i < row_size; i++)
        array[i] = (int*)malloc(sizeof(int)*colum_size);  
    return array;
}

void free_2d_arr(int** matrix,int row_size, int colum_size) {
    for (int i = 0; i < row_size; i++) {
        free(matrix[i]);
    }
    free(matrix);
}

int main(int argc, char const *argv[])
{
    int row=3,cloum=2;
    int** arr_2d = create_2d_arr(row,cloum);

    arr_2d[0,0]=4;
    arr_2d[0,1]=5;

    arr_2d[1,0]=6;
    arr_2d[1,1]=7;

    arr_2d[2,0]=8;
    arr_2d[2,1]=9;

    for(int i=0;i<row;i++)
    for(int j=0;j<cloum;j++)
    printf("arr_2d[%d,%d] = %d \n",i,j,arr_2d[i,j]);

    free_2d_arr(arr_2d,row,cloum);

    return 0;
}

However, there are errors when executing after compilation:

arr_2d[0,0] = 8 
arr_2d[0,1] = 9 
arr_2d[1,0] = 8 
arr_2d[1,1] = 9 
arr_2d[2,0] = 8 
arr_2d[2,1] = 9 
[1]    9300 segmentation fault (core dumped)  ./t

Only arr_2d[2,0]=8 arr_2d[2,1]=9 are correct. I don't understand where my code is wrong. Does anyone help me?


renew

thanks for your replies. but after I modify arr_2d[2,0]=8 to arr_2d[2][0]=8 ...

result of printf is
arr_2d[0][0] = -267545984
arr_2d[0][1] = -267545952
arr_2d[1][0] = -267545984

...

warning of compiler

t.c:38:47: warning: expression result unused [-Wunused-value]
    printf("arr_2d[%d,%d] = %d \n",i,j,arr_2d[i,j]);
                                              ^
t.c:38:40: warning: format specifies type 'int' but the argument has type
      'int *' [-Wformat]
    printf("arr_2d[%d,%d] = %d \n",i,j,arr_2d[i,j]);
                            ~~         ^~~~~~~~~~~
2 warnings generated.

my compiler is clang,even if I use gcc

=========

Solved

After modify:

printf("arr_2d[%d,%d] = %d \n",i,j,arr_2d[i,j]);

=>

printf("arr_2d[%d,%d] = %d \n",i,j,arr_2d[i],[j]);

It work normally. Thank everyone very much.

D.Wei
  • 55
  • 9
  • 3
    `arr_2d[0,0]=4;` -> `arr_2d[0][0]=4;` – Osiris Jan 11 '19 at 13:17
  • 1
    How many compiler warnings did your compiler give you for this code? – hetepeperfan Jan 11 '19 at 13:29
  • 1
    I would suspect that you did not change it in `printf`. – Osiris Jan 11 '19 at 13:33
  • Do you use the flags -Wall to turn on extra warnings. I would advise that. – hetepeperfan Jan 11 '19 at 13:35
  • Hi Osiris, thanks your hints.It work normally. – D.Wei Jan 11 '19 at 13:35
  • Stay clear of crappy internet tutorials. See [Correctly allocating multi-dimensional arrays](https://stackoverflow.com/questions/42094465/correctly-allocating-multi-dimensional-arrays) for how to do it in C. In C++ you would preferably use std::vector. – Lundin Jan 11 '19 at 13:50
  • the posted code results in a LONG lost of warnings from the compiler. When compiling, always enable the warnings, then fix those warnings ( for `gcc` at a minimum use: `-Wall -Wextra -Wconversion -pedantic -std=gnu11` ) Note other compilers use different options to produce the same output – user3629249 Jan 12 '19 at 20:06
  • this kind of statement: `arr_2d[0,0]=4;` is not valid, suggest: `arr_2d[0][0]=4;` – user3629249 Jan 12 '19 at 20:07
  • OT: regarding this kind of statement: `array[i] = (int*)malloc(sizeof(int)*colum_size);` 1) when calling any of the heap allocation functions: `malloc` `calloc` `realloc`, always check (!=NULL) the returned value to assure the operation was successful. If not successful, output your error message and the text reason the error occurred to `stderr`. The easiest way to do that is by calling `perror( "your error message" );` 2) in C, the returned type is `void*` which can be assigned to any pointer, Casting just clutters the code, making it more difficult to understand, debug, etc – user3629249 Jan 12 '19 at 20:11
  • for ease of readability and understanding, 1) do not leave out optional opening and closing braces '{' and '}'. – user3629249 Jan 12 '19 at 20:17
  • OT: regarding: `void free_2d_arr(int** matrix,int row_size, int colum_size)` In this function, the parameter `colum_size` is not used, To avoid a compiler warning, either remove that parameter or the first statement in the body of the function should be: `(void)colum_size);` – user3629249 Jan 12 '19 at 20:21
  • OT: regarding: `int main(int argc, char const *argv[])` When the parameters are not going to be used, the correct signature for `main()` is: `int main( void )` otherwise the compiler will output to warning messages about unused parameters – user3629249 Jan 12 '19 at 20:23
  • regarding this kind of statement: `arr_2d[0,1]=5;` the `[0,1]` is a `comma` expression where the first expresion `1` does nothing. What you really want is: `arr_2d[0][1]=5;` – user3629249 Jan 12 '19 at 20:25

4 Answers4

2

you can't access array's value like this

arr_2d[x,y];

you have to use this type of syntax

arr_2d[x][y];
  • Actually you can, but it is not a very helpful way... https://stackoverflow.com/questions/34098166/comma-operator-with-indexing-2d-arrays – Jose Jan 11 '19 at 13:36
  • 1
    I don't think you can, what a comma operator does, it it just evaluates each part and return the last evaluated part so arr_2d[2,23,6,23,56,2] is kinda useless you could just use arr_2d[2] and you'd have the same thing. Additionally if it's a 2D array, arr_2d[x,y] would return an array of `int/char..` –  Jan 11 '19 at 14:00
  • [... it it just evaluates each part and return the last evaluated part...], so you can. – Jose Jan 11 '19 at 14:06
1

arr_2d[x,y] is equivalent to arr_2d[y]

use arr_2d[x][y] in assignment and access

In C (or C++) a,b,c .., z compute a then b .. then z and returns the value of z


So :

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

int** create_2d_arr(int row_size,int colum_size)
{
    int** array = (int**)malloc(sizeof(int*)*row_size);
    int i;
    for ( i = 0; i < row_size; i++)
        array[i] = (int*)malloc(sizeof(int)*colum_size);  
    return array;
}

void free_2d_arr(int** matrix,int row_size, int colum_size) {
  int i;
    for ( i = 0; i < row_size; i++) {
        free(matrix[i]);
    }
    free(matrix);
}

int main(int argc, char const *argv[])
{
    int row=3,cloum=2;
    int** arr_2d = create_2d_arr(row,cloum);

    arr_2d[0][0]=4;
    arr_2d[0][1]=5;

    arr_2d[1][0]=6;
    arr_2d[1][1]=7;

    arr_2d[2][0]=8;
    arr_2d[2][1]=9;

    int i,j;
    for( i=0;i<row;i++)
    for( j=0;j<cloum;j++)
    printf("arr_2d[%d][%d] = %d \n",i,j,arr_2d[i][j]);

    free_2d_arr(arr_2d,row,cloum);

    return 0;
}

The result is :

arr_2d[0][0] = 4 
arr_2d[0][1] = 5 
arr_2d[1][0] = 6 
arr_2d[1][1] = 7 
arr_2d[2][0] = 8 
arr_2d[2][1] = 9 
bruno
  • 32,421
  • 7
  • 25
  • 37
0

The correct syntax is

arr_2d[i][j] = n;

I have never seen something like arr_2d[i,j] and would be great-full if someone explained it to us.

My guess is that it's equivalent to arr_2d[j] but I'm not sure.

EDIT: precision: you should change ALL your arr_2d[i,j] (like arr_2d[0,0]) to the new syntax

Fayçal Borsali
  • 402
  • 4
  • 17
0

the following proposed code:

  1. cleanly compiles
  2. performs the desired functionality
  3. incorporates my comments to the OPs question
  4. for readability, inserts an appropriate space: inside parens, inside braces, after semicolons, after commas, around C operators
  5. used size_t rather than int to avoid compiler warnings about conversions between int and size_t, especially in the calls to calloc() and malloc()

And now, the proposed code:

#include <stdio.h>
#include <stdlib.h>   // exit(), EXIT_FAILURE


// prototypes
void free_2d_arr( int** matrix, size_t row_size, size_t colum_size );


int** create_2d_arr( size_t row_size, size_t colum_size )
{
    int** array = calloc( row_size, sizeof( int* ) );
    if( !array )
    {
        perror( "malloc failed" );
        exit( EXIT_FAILURE );
    }

    // implied else, malloc successful

    for ( size_t i = 0; i < row_size; i++ )
    {
        array[ i ] = malloc( sizeof(int) * colum_size );  
        if( !array[ i ] )
        {
            perror( "malloc failed" );
            free_2d_arr( array, row_size, colum_size ); 
            exit( EXIT_FAILURE );
        }
    }
    return array;
}


void free_2d_arr( int** matrix, size_t row_size, size_t colum_size ) 
{
    (void)colum_size;
    for ( size_t i = 0; i < row_size; i++ ) 
    {
        free( matrix[ i ] );
    }
    free( matrix );
}


int main( void )
{
    size_t row = 3;
    size_t cloum = 2;
    int** arr_2d = create_2d_arr( row, cloum );

    arr_2d[ 0 ][ 0 ] = 4;
    arr_2d[ 0 ][ 1 ] = 5;

    arr_2d[ 1 ][ 0 ] = 6;
    arr_2d[ 1 ][ 1 ] = 7;

    arr_2d[ 2 ][ 0 ] = 8;
    arr_2d[ 2 ][ 1 ] = 9;

    for( size_t i=0; i < row; i++ )
    {
        for( size_t j=0; j < cloum; j++ )
        {
            printf( "arr_2d[%lu,%lu] = %d \n", i, j, arr_2d[ i ][ j ] );
        }
    }

    free_2d_arr( arr_2d, row, cloum );

    return 0;
}

a run of the proposed code results in:

arr_2d[0,0] = 4 
arr_2d[0,1] = 5 
arr_2d[1,0] = 6 
arr_2d[1,1] = 7 
arr_2d[2,0] = 8 
arr_2d[2,1] = 9 

Note, however, that the statements:

size_t row = 3;
size_t cloum = 2;

are really parameters to the program and the 2 and 3 are constants and 'magic' numbers. 'magic' numbers are numbers with no basis. 'magic' numbers make the code more difficult to understand, debug, etc. Suggest using #define statements or a enum statement to give those 'magic' numbers meaningful names, then use those meaningful names throughout the code

user3629249
  • 16,402
  • 1
  • 16
  • 17