1

I was asked to write a program that produces a 2d array of random numbers. My code produces strange results. Regardless of the size of the matrix it produces a "reverse diagonal matrix" (not sure what else to call it). I was to understand that rand() produces a pseudorandom number between 0 and RAND_MAX but somehow the results are dependent on the size of my matrix, I am unsure how this behavior could happen.

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

#define MAT_SIZE 5

void main (void)
{

srand(time(0));

unsigned char * ptr = malloc(MAT_SIZE*MAT_SIZE);
unsigned char i, j;

for(i = 0; i < MAT_SIZE; i++)
{
    for(j = 0; j < MAT_SIZE ; j ++)
    {

        *(ptr + i + j ) = rand();
    }
}
 for(i = 0; i < MAT_SIZE ; i++)
{
    for(j = 0; j < MAT_SIZE ; j ++)
    {
        printf("%5d", *(ptr + i + j));
    }
    printf("\n");
}
    free(ptr);
}

Output for 3*3

142  141   11
141   11  230
11   230   28

Output for 5*5

232  157   62  131  245
157   62  131  245   54
 62  131  245   54  138
131  245   54  138  246
245   54  138  246  108

Even a pseudorandom number shouldn't behave differently based on how it is used. Is there something I'm not understanding about the program that forces these results?

4
  • 1
    Your code would be much simpler if, instead of allocating a block of memory and trying to map a matrix into it, you simply declared and used a matrix directly: i.e. int matrix[MAT_SIZE][MAT_SIZE];
    – Ferruccio
    Commented Sep 12, 2013 at 18:07
  • *(ptr + i + j ) ==> *(p[i]+j)
    – Gangadhar
    Commented Sep 12, 2013 at 18:07
  • 1
    Nope gangadhar, that's a segfault. p[i] is a char, not a pointer.
    – Dan
    Commented Sep 12, 2013 at 18:10
  • 1
    @Ferruccio, you should have elaborated that into an answer. Unfortunately, there is still a lot of code around that sells such "emulation" of 2D arrays to beginners instead of teaching them the right thing from the start. Commented Sep 12, 2013 at 19:08

3 Answers 3

8

The problem is not with the random numbers that are generated but with how you are saving them in your matrix. To access element (j, i) you do not want

*(ptr + i + j )

but

*(ptr + MAT_SIZE * i + j )
2

You are only accessing the first i+j members of the array, and looping over the same indices repeatedly. Instead of:

*(ptr + i + j )

Try

*(ptr + i * MAT_SIZE + j )

0

Note that you can dynamically allocate a 2D array as follows:

unsigned char (*ptr)[MAT_SIZE] = malloc( MAT_SIZE * sizeof *ptr );
...
ptr[i][j] = rand();
...
free( ptr );

Makes life a little simpler. This way you can use normal 2D array indexing instead of having to map i and j to a single dimension.

Nits:

Unless your compiler documentation explicitly lists void main() as a valid signature for main, use int main( void ) instead. I know you've seen thousands of examples of void main() in books and on line, but just because the compiler doesn't complain about it doesn't mean it isn't wrong.

rand() returns int, which will not fit into an unsigned char. Overflow on unsigned types is well-defined, but even so, you may want to explicitly map your rand result onto the range [0..255].

Not the answer you're looking for? Browse other questions tagged or ask your own question.