Note that there are some explanatory texts on larger screens.

plurals
  1. POCan you pass multi-dimensional arrays into a C function as pointers and then cast them back into arrays inside the function?
    primarykey
    data
    text
    <p><strong>Problem:</strong> suppose you are trying to write a function in C that will fill a 2D array with values from a file. The file contains the values arranged in rows (records), where each row contains a number of fields. The function should take in a pointer to the 2D array and the address of the file and fill in the array. Importantly, the function should work independently of how many fields there are per record. For example, in one program you might call the function to read values from a file where there are four fields per record: </p> <pre><code>int array_of_values[MAX_NUMBER_OF_RECORDS][4]; fill_in_array(array_of_values, "spacetime.csv"); </code></pre> <p>In another program, you might want to fill in values when there are eleven fields per record:</p> <pre><code>int array_of_values[MAX_NUMBER_OF_RECORDS][11]; fill_in_array(array_of_values, "M-theory.csv"); </code></pre> <p>Unfortunately, if you try to do this you fall foul of the way C handles multidimensional arrays. Multidimensional arrays are not implemented in C as arrays of pointers to arrays, but instead as one long one-dimensional array. This means that the function needs to know the width of the array in order to read data from it. </p> <p>So the following function definition will give you an error:</p> <pre><code>void fill_in_array(int array_of_values[MAX_NUMBER_OF_RECORDS][], char *path) </code></pre> <p>[Note that the following would be fine:</p> <pre><code>void fill_in_array(int array_of_values[][MAX_NUMBER_OF_RECORDS], char *path) </code></pre> <p>since the compiler does not need to know the index for the first dimension, but suppose that this is not allowed (e.g., if the function needs to mess around with individual records like <code>array_of_values[1]</code>).]</p> <p>This is the point that I have reached in my program. There are two solutions that present themselves: </p> <ol> <li>Force the function to work with a fixed number of fields. I'd obviously rather not do this, but I could, for example, declare a constant <code>MAX_NUMBER_OF_FIELDS</code> and leave unused fields empty.</li> <li>Make the <code>fill_in_array</code> function take in a pointer rather than an array and dynamically allocate an Iliffe vector containing the fields. This is an attractive idea (since it would stop us having to declare a maximum number of records/fields, but it would also mean we would have to create (and remember to use!) a function to free the array of fields. </li> </ol> <p>I've got one other idea. That is to modify the declaration of the function to the following:</p> <pre><code>void fill_in_array(int **array_of_values, int number_of_fields, char *path) </code></pre> <p>(Here, <code>number_of_fields</code> refers to the number of fields per record, so we might call it as <code>fill_in_array(array_of_values, 4, "spacetime.csv");</code>. </p> <p>Notice that the parameter <code>array_of_values</code> is no longer an explicit array, but is a pointer. Normally, if you assign a double-pointer to point to a 2D array, the result is meaningless. My idea is that it might be possible to use the <code>number_of_fields</code> parameter so that the function knows how to deal with expressions like <code>array_of_values[i][j]</code>.</p> <p>In principle this should be fairly easy: indeed, if <code>a</code> is a 2D array, then <code>a[i][j]</code> is defined to be</p> <pre><code>*(a + (i * n) + j) </code></pre> <p>where <code>n</code> is the length of the array, so we could replace every occurrence of <code>array_of_values[i][j]</code> with <code>*(array_of_values + (i * number_of_fields) + j)</code>, and every occurrence of <code>array_of_values[i]</code> with <code>array_of_values + (i * number_of_fields)</code>. This code would be very hard to read, however. Is there some way of telling the compiler that the width of the array is <code>number_of_fields</code> so that I can use index notation to access elements of the array?</p>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload