-1

An example to illustrate:

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

void simple_function(int s , int array[][s]);

int main(void){

int x;
/*Static 2D Array*/
int array[2][2];

/*Many Methods to Dynamically Allocate 2D Array....for example*/

/* Using Array of pointers*/
int *array1[2];
for(x=0;x<2;x++){array1[x] = calloc (2, sizeof(int));}

/*Using pointer to a pointer */
int **array2 = calloc (2, sizeof(int*));
for(x=0;x<2;x++){array2[x] = calloc (2, sizeof(int));}

/*Using a single pointer*/
int *array3 = calloc (4 , sizeof(int));



/* Codes To Fill The Arrays*/


/*Passing the Arrays to the function, some of them won't work*/
simple_function(2, array);  /*Case 1*/
simple_function(2, array1); /*Case 2*/
simple_function(2, array2); /*Case 3*/
simple_function(2, array3); /*Case 4*/

return 0;
}


void simple_function (int s, int array[][s]){

int x,y;

for(x=0;x<s;x++){
   for(y=0;y<s; y++){
    printf ("Content is %d\n", array[x][y]);
}
}
}

My Question: Is there a way to write the signature of the simple_function to let it accepts all cases regardless of the method that the user chose? If not, what is the most preferable for the function if I want to make a library?

  • `array[x] = calloc (2, sizeof(int));` You should start from here. What is ARRAY? – Michi Jul 18 '16 at 22:07
  • 1
    Your premise is wrong already. There is only one way to allocate a 2D array. Something like `int **` is not a 2D array and cannot represent one. A pointer is not an array and vice-versa. The rest shown is a variation of these two different things when it comes to passing to a function. – too honest for this site Jul 18 '16 at 22:12
  • @Olaf , O.K I know that , but what if the user wanted to create 2D array in that method, how would my function handle it? –  Jul 18 '16 at 22:14
  • @John If so, please explain what does mean this line `array[x] = calloc (2, sizeof(int));` in your program. – Michi Jul 18 '16 at 22:17
  • @John You need a `Pointer` there , but you have an `Array`. Do you get the point? – Michi Jul 18 '16 at 22:20
  • `pointer to pointer to create a 2D array` NO, a pointer-to-pointer creates a pointer lookup table which maybe at some point does the same thing like an multidimensional Array, but it will never be one. – Michi Jul 18 '16 at 22:22
  • 1
    @John: "O.K I know that , but what if the user wanted to create 2D array in that method" - Please step back and read that sentence carefully. You are aware that you contradict yourself in that single sentence, are you? Re. your book: It apparently is outdated and was never right with that term. Likely the book does not even cover C99 (bad reputation for a book released in 2003). – too honest for this site Jul 18 '16 at 22:26
  • @Michi: It cannot even point to a multidimensional array. Just to a 1D array (as given here). You can very well have something like "array of pointers to multidimensional array" (I'm too lazy right now to figure out a declarator for that - feel free to try yourself:-), but that's not what OP comes even close to (useless anyway for 2 layer lookup). – too honest for this site Jul 18 '16 at 22:31
  • so you're saying that creating pointer of pointer is not a 2D array... would one of the downvoters reward me with a correct reference of multi-diminstional arrays –  Jul 18 '16 at 22:56
  • the problem is that I did not write the codes from my mind, I read 2 books and looked at more than 5 websites of how to create multi-dimensional arrays in the last 2 months ... and I only copied-pasted what is there! How can we learn if you react like that... I promise God when I become a competent programmer, I won't treat learners like what you do. –  Jul 18 '16 at 23:01
  • @John: How about showing at least some minor effort on your own? As I wrote, there are plenty of Q&A here about that subject already. Just filter the wrongs with `int **` or similar (you are cefinitively not the only to confuse this). It actually is pretty simple.. – too honest for this site Jul 18 '16 at 23:16
  • @Olaf what do you think about the websites I mentioned and the books?! –  Jul 18 '16 at 23:33
  • from http://www.geeksforgeeks.org/dynamically-allocate-2d-array-c/ "How to dynamically allocate a 2D array in C? Following are different ways to create a 2D array on heap (or dynamically allocate a 2D array)." "3) Using pointer to a pointer: int **arr = (int **)malloc(r * sizeof(int *)); for (i=0; i –  Jul 18 '16 at 23:36
  • from http://c-faq.com/aryptr/dynmuldimary.html "How can I dynamically allocate a multidimensional array?" "he traditional solution is to allocate an array ]of pointers to pointers, and then initialize each pointer to a dynamically-allocated ``row.'' Here is a two-dimensional example: #include int **array1 = malloc(nrows * sizeof(int *)); for(i = 0; i < nrows; i++) array1[i] = malloc(ncolumns * sizeof(int));" –  Jul 18 '16 at 23:36
  • from http://pleasemakeanote.blogspot.ie/2008/06/2d-arrays-in-c-using-malloc.html "Pointers can be easily used to create a 2D array in C using malloc." "Here's a sample code: double** theArray; theArray = (double**) malloc(arraySizeX*sizeof(double*)); for (int i = 0; i < arraySizeX; i++) theArray[i] = (double*) malloc(arraySizeY*sizeof(double));" –  Jul 18 '16 at 23:38
  • from ((A TUTORIAL ON POINTERS AND ARRAYS IN C by Ted Jensen Version 1.2 (PDF Version) Sept. 2003)) "METHOD 3: Consider the case where we do not know the number of elements in each row at compile time, i.e. both the number of rows and number of columns must be determined at run time. One way of doing this would be to create an array of pointers to type int and then allocate space for each row and point these pointers at each row. Consider: int **rowptr; rowptr = malloc(nrows * sizeof(int *)); for (row = 0; row < nrows; row++) { rowptr[row] = malloc(ncols * sizeof(int));" –  Jul 18 '16 at 23:41
  • http://stackoverflow.com/questions/917783/how-do-i-work-with-dynamic-multi-dimensional-arrays-in-c Is there a mistake in this 60 upvote ? really shame. –  Jul 18 '16 at 23:48
  • @John: Well, apparently it plain wrong (I think I and others here were very clear about this already). Some of these techniques (e.g. using a 1D array and emulate the 2D indexing) are for pre-C99 and outdated. – too honest for this site Jul 18 '16 at 23:49

3 Answers3

2

You've actually declared two different types of objects, as shown below

enter image description here

Your array and array3 are both stored in memory as 4 contiguous ints. There's no additional information, you've simply reserved space for 4 ints, and the C specification requires that they are contiguous.

However, array1 and array2 are actually pointer arrays. Your code reserves memory for an array of two pointers, and each pointer points to an array of two ints. The ints will be arranged in groups of two, but the groups can be scattered anywhere in memory.

From this, it should be clear that the compiler cannot use the same code to access both types of array. For example, let's say that you're trying to access the item at array[x][y]. With a contiguous array, the compiler computes the address of that item like this

address = array + (x * s + y) * sizeof(int)

With a scattered array, the compiler computes the address like this

pointer = the value at {array + x * sizeof(int *)}
address = pointer + y * sizeof(int)

So you need two functions to handle those two cases. For the contiguous array, the function looks like this

void showContiguousArray( int s, int array[][s] )
{
    for ( int x=0; x<s; x++ )
        for ( int y=0; y<s; y++ )
            printf( "array[%d][%d] = %d\n", x, y, array[x][y] );
}

For the scattered array, the function is

void showScatteredArray( int s, int **array )
{
    for ( int x=0; x<s; x++ )
        for ( int y=0; y<s; y++ )
            printf( "array[%d][%d] = %d\n", x, y, array[x][y] );
}

Notice that those functions are identical, except for one thing, the type of the array argument. The compiler needs to know the type in order to generate the correct code.

If the array is declared in the same scope where it's used, then all of these details are hidden, and it seems that you're using the exact same code to access different types of arrays. But that only works because the compiler knows the type of the array from the earlier declaration. But if you want to pass the array to a function, then the type information must be explicitly specified in the function declaration.

user3386109
  • 34,287
  • 7
  • 49
  • 68
1

Is there a way to write the signature of the simple_function to let it accepts all cases regardless of the method that the user chose?

"All the cases" apparently describes the different declarations array, array1, array2, and array3, the latter three of which are described in code comments as "Methods to Dynamically Allocate 2D Array." But none of the four types are the same as any of the others, and none of the latter three in fact declare 2D arrays nor pointers to such. None of them are even compatible with each other. Of the dynamic ones, only array3 can even usefully be converted to something comparable to array.

A dynamically-allocated 2D array would be referenced via a pointer of this type:

int (*array4)[2];

array4 = calloc(2 * sizeof(*array4));

So, no.

If not, what is the most preferable for the function if I want to make a library?

It depends on your objectives. If your function must be compatible with static 2D arrays, then something of the general form you presented, plus or minus the variable dimension, is the only alternative. If you want to support the pointer-to-pointer form, then that's fine, and usable with declarations like array1's and array2's, but not with array, array3, or array4.

John Bollinger
  • 160,171
  • 8
  • 81
  • 157
0

Assuming that you want this for 2D arrays, perhaps this can get you started ...

void simple_function(int s, int t , int* array) {

  int i, j;

  for (i=0; i<s; i++) {
      for (j=0; j<t; j++) {

         // accessing your array elements
             printf(" %d", *(array + i*t + j));
      }

      printf("\n");

  }

}

int main(void)
{

  int array[2][3];


  array[0][0] = 1;
  array[0][1] = 2;
  array[0][2] = 3;
  array[1][0] = 11;
  array[1][1] = 12;
  array[1][2] = 13;
  array[2][0] = 21;
  array[2][1] = 22;
  array[2][2] = 23;

  simple_function(3, 3 , array);

  return 0;

}

The expression int **array2 is not a 2D array by the way, it is a variable that holds the address of a pointer variable.

clarasoft-it
  • 201
  • 1
  • 5