0

I declare hws globally and try to return it in this method but I get a pointer error. I was wondering if anyone knew why that is and could suggest a solution? Randomize just get a random number.

extern int hws[100][20];

int randomize()
{

    int value;
    int tru_fals = 0;
    value = -1;
    while ( tru_fals != 1 )
    {
        value = rand();
        if ( 0 < value )
        {
            if( 101 > value )
            {
                tru_fals = 1;
            }
        }
    }
    return value;

}
int *populate()
{

    int i, j;

    i = 0;
    j = 0;
    while( i < 20 )
    {
        while ( j < 100)
        {
            int temp = randomize();
            hws[i][j] = temp;
            j++;
        }
        i++;
    }
    return hws;

}
2
  • 1
    hws is not an array. it's an array of arrays. Commented Sep 20, 2012 at 18:35
  • 2
    If it's global, why return it? Just access it everywhere... Commented Sep 20, 2012 at 18:36

5 Answers 5

2

there is a bug: the array is declared as 100x20 but then you iterate through it like it is 20x100.

Sign up to request clarification or add additional context in comments.

Comments

2

You define extern int hws[100][20];.
This doesn't create any array. It just says that somewhere in the program, there should be one.

To make it work, some other source file must really define the array - int hws[100][20]; (without extern). Then, if you compile both and link together, it should work.

If you only want one source file, it's much easier - just remove extern.

But: Just noticed Serge's answer, which is actually the real cause of the problem.

Comments

1

Except when it is the operand of the sizeof, _Alignof, or unary & operator, or is a string literal being used to initialize another array in a declaration, an expression of type "N-element array of T" will be converted ("decay") to an expression of type "pointer to T", and its value will be the address of the first element in the array (6.3.2.1/3).

In the line return hws; in populate, the type of the expression hws is "100-element array of 20-element array of int"; by the rule above, it will be converted to type "pointer to 20-element array of int", or int (*)[20]. Thus, the correct declaration for populate would need to be

int (*populate())[20]
{
   ...
   return hws;
}

which reads as

      populate           -- populate
      populate()         -- is a function
     *populate()         -- returning a pointer
    (*populate())[20]    -- to a 20-element array
int (*populate())[20]    -- of int.

and the type of whatever you return the result to would need to be int (*)[20] as well.

Having said that...

Using global variables this way is highly discouraged for a number of reasons. It would be better to pass the array in to populate as a parameter, like so:

void populate(int (*arr)[20], size_t rows)
{  
  size_t i, j;

  for (i = 0; i < rows; i++)
  {
    for (j = 0; j < 20; j++)
    {
      arr[i][j] = randomize();
    }
  }
}

You would call this as simply

populate(hws, sizeof hws / sizeof hws[0]);

If you're using a compiler that supports variable length arrays (either a C99 compiler or a C2011 compiler that does not define __STDC_NO_VLA__ or defines it to 0), you could define the function as

void populate(size_t cols, size_t rows, int (*arr)[cols]) // cols must be declared
{                                                         // before it can be used
  size_t i, j;                                            // to declare arr

  for (i = 0; i < rows; i++)
  {
    for (j = 0; j < cols; j++)
    {
      arr[i][j] = randomize();
    }
  }
}

and call it as

size_t rows = sizeof hws[0] / sizeof hws[0][0];  // dividing the size of the array
size_t cols = sizeof hws / sizeof hws[0];        // by the size of the first element
populate(cols, rows, hws);                       // gives the number of elements

so you're not hardcoding the 20 anywhere.

If you aren't using a compiler that supports variable length arrays, and you don't want to hardcode the number of rows in the function prototype, you can do something like this:

void populate(int *arr, size_t rows, size_t cols)
{
  size_t i, j;
  for (i = 0; i < rows; i++)
  {
    for (j = 0; j < cols; j++)
    {
      arr[i * rows + j] = randomize();
    }
  }
}

and call it as

// rows and cols calculated as above
populate(&hws[0][0], rows, cols);

In this case, instead of passing a pointer to the array, we pass a pointer to the first element (the address value is the same, but the type is int * instead of int (*)[20]. So the populate function treats it like a 1D array, and computes the offset with i * rows + j. Note that this trick will only work for 2D arrays that have been allocated contiguously.

This also means that populate can work with arrays of any size, not just Nx20.

Comments

0

hws is a matrix, it means that its and int **

You are returning and int * so you are having a pointer type mismatch.

2 Comments

You're wrong here. A matrix isn't an array of arrays, it's just a bunch of integers (2000 in this case). When returning it, it decays to int *, not int **.
You're both wrong. hws decays to int (*)[20] (pointer to 20-element array of int).
0

First, it doesn't need to be returned since it's global. Second, it is a pointer to a pointer to an int. It's an array of an array.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.