optimusfrenk
optimusfrenk

Reputation: 1321

initialize a global 2-dimensional C array of integers at run time

I need to store an array of point (x,y). I read the points from a file, and the number of points are not constant, but i can get it at the first line of the file. So i write a procedure load() to loading the points from the file and store them in a global array. It doesn't work. My code:

int *array[][]; // this is a pointer to a 2-dimensional array??

void load(){
..
int tempArray[2][n];  //n is the first line of the file
..
array = tempArray;
}

Upvotes: 1

Views: 2845

Answers (4)

Jonathan Leffler
Jonathan Leffler

Reputation: 753960

This declaration of yours does not work:

int *array[][]; // this is a pointer to a 2-dimensional array??

First, it is trying to declare a 2D array of int *. Second, when you declare or define an array, all dimensions except the first must be specified (sized).

int (*array)[][2];   // This is a pointer to a 2D array of unknown size

This could now be used in a major variant of your function. It's a variant because I misread your question at first.

void load(void)
{
    ...
    int tempArray[n][2];  // Note the reversed order of dimensions!
    ...
    array = &tempArray;
    ...there must be some code here calling functions that use array...
    array = 0;
}

Note that the assignment requires the & on the array name. In the other functions, you'd need to write:

n = (*array)[i][j];

Note, too, that assigning the address of a local array to a global variable is dangerous. Once the function load() returns, the storage space for tempArray is no longer valid. Hence, the only safe way to make the assignment is to then call functions that reference the global variable, and then to reset the global before exiting the function. (Or, at least, recognize that the value is invalid. But setting it to zero - a null pointer - will more nearly ensure that the program crashes, rather than just accessing random memory.

Alternatively, you need to get into dynamic memory allocation for the array.

Your question actually is wanting to make a global pointer to a VLA, variable-length array, where the variable dimension is not the first:

int tempArray[2][n];  // Note the reversed order of dimensions!

You simply can't create a global pointer to such an array.

So, there are multiple problems:

  • Notation for pointers to arrays
  • Initializing pointers to arrays
  • Assigning global pointers to local variables
  • You can't have global pointers to multi-dimensional VLAs where the variable lengths are not in the first dimension.
  • You should minimize the use of globals.

Upvotes: 2

ouah
ouah

Reputation: 145839

You are trying to assign an array but in C arrays cannot be assigned.

Use memcpy to copy one array to another array. Arrays elements in C are guaranteed to be contiguous.

int bla[N][M] = {0};
int blop[N][M];

/* Copy bla array to blop */
memcpy(blop, bla, sizeof blop);

Upvotes: 0

Kerrek SB
Kerrek SB

Reputation: 477060

A more elegant version might go like this:

typedef struct point_ { int x; int y; } point;

point * create_array(size_t n)
{
    return calloc(n, sizeof(point));
}

void free_array(point * p)
{
    free(p);
}

int main()
{
    size_t len = read_number_from_file();
    point * data = create_array(len);

    if (!data) { panic_and_die(); }

    for (size_t i = 0; i != len; ++i)
    {
        /* manipulate data[i].x and data[i].y */
    }

    free_array(data);
    data = 0;            /* some people like to do this */
}

Upvotes: 0

unwind
unwind

Reputation: 399843

You're trying to return a pointer to memory that is local to the function that defines the variable. Once that function stops running ("goes out of scope"), that memory is re-used for something else, so it's illegal to try and reference it later.

You should look into dynamic allocation, and have the loading function allocate the needed memory and return it.

The function prototype could be:

int * read_points(const char *filename, size_t *num_points);

Where filename is of course the name of the file to open, num_points is set to the number of points found, and the returned value is a pointer to an array holding x and y values, interleaved. So this would print the coordinates of the first point loaded:

size_t num_points;
int    *points;

if((points = load_points("my_points.txt", &num_points)) != NULL)
{
  if(num_points > 0)
    printf("the first point is (%d,%d)\n", points[0], points[1]);
  free(points);
}

Upvotes: 3

Related Questions