By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
431,731 Members | 1,123 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 431,731 IT Pros & Developers. It's quick & easy.

Passing 2D array to a function using single pointer .

P: 56
Expand|Select|Wrap|Line Numbers
  1. #include <stdio.h>
  2. void print(int *arr, int m, int n)
  3. {
  4. int i, j;
  5. for (i = 0; i < m; i++)
  6. for (j = 0; j < n; j++)
  7. printf("%d ", *((arr+i*n) + j));
  8. }
  9. int main()
  10. {
  11. int arr[][3] = {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}};
  12. int m = 3, n = 3;
  13.  
  14. print((int *)arr, m, n);
  15. return 0;
  16. }
  17.  
Why can't I use *(*(arr+i)+j) notation inside printf in print function .Although it's a pointer to an integer still I am operating on the address of first element of array , so what's wrong in this ?
Apr 8 '17 #1

✓ answered by hackr

1) When both dimensions are available globally (either as a macro or as a global constant).

Expand|Select|Wrap|Line Numbers
  1. #include <stdio.h>
  2. const int M = 3;
  3. const int N = 3;
  4.  
  5. void print(int arr[M][N])
  6. {
  7.     int i, j;
  8.     for (i = 0; i < M; i++)
  9.       for (j = 0; j < N; j++)
  10.         printf("%d ", arr[i][j]);
  11. }
  12.  
  13. int main()
  14. {
  15.     int arr[][N] = {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}};
  16.     print(arr);
  17.     return 0;
  18. }
Run on IDE
Output:
Expand|Select|Wrap|Line Numbers
  1. 1 2 3 4 5 6 7 8 9
2) When only second dimension is available globally (either as a macro or as a global constant).

Expand|Select|Wrap|Line Numbers
  1. #include <stdio.h>
  2. const int N = 3;
  3.  
  4. void print(int arr[][N], int m)
  5. {
  6.     int i, j;
  7.     for (i = 0; i < m; i++)
  8.       for (j = 0; j < N; j++)
  9.         printf("%d ", arr[i][j]);
  10. }
  11.  
  12. int main()
  13. {
  14.     int arr[][3] = {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}};
  15.     print(arr, 3);
  16.     return 0;
  17. }
Run on IDE
Output:

Expand|Select|Wrap|Line Numbers
  1. 1 2 3 4 5 6 7 8 9
The above method is fine if second dimension is fixed and is not user specified. The following methods handle cases when second dimension can also change.

3) If compiler is C99 compatible
From C99, C language supports variable sized arrays to be passed simply by specifying the variable dimensions (See this for an example run)

Expand|Select|Wrap|Line Numbers
  1. // The following program works only if your compiler is C99 compatible.
  2. #include <stdio.h>
  3.  
  4. // n must be passed before the 2D array
  5. void print(int m, int n, int arr[][n])
  6. {
  7.     int i, j;
  8.     for (i = 0; i < m; i++)
  9.       for (j = 0; j < n; j++)
  10.         printf("%d ", arr[i][j]);
  11. }
  12.  
  13. int main()
  14. {
  15.     int arr[][3] = {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}};
  16.     int m = 3, n = 3;
  17.     print(m, n, arr);
  18.     return 0;
  19. }
Run on IDE
Output on a C99 compatible compiler:

Expand|Select|Wrap|Line Numbers
  1. 1 2 3 4 5 6 7 8 9
If compiler is not C99 compatible, then we can use one of the following methods to pass a variable sized 2D array.

4) Using a single pointer
In this method, we must typecast the 2D array when passing to function.

Expand|Select|Wrap|Line Numbers
  1. #include <stdio.h>
  2. void print(int *arr, int m, int n)
  3. {
  4.     int i, j;
  5.     for (i = 0; i < m; i++)
  6.       for (j = 0; j < n; j++)
  7.         printf("%d ", *((arr+i*n) + j));
  8. }
  9.  
  10. int main()
  11. {
  12.     int arr[][3] = {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}};
  13.     int m = 3, n = 3;
  14.  
  15.     // We can also use "print(&arr[0][0], m, n);"
  16.     print((int *)arr, m, n);
  17.     return 0;
  18. }
Run on IDE
Output:

Expand|Select|Wrap|Line Numbers
  1. 1 2 3 4 5 6 7 8 9

Share this Question
Share on Google+
9 Replies


weaknessforcats
Expert Mod 5K+
P: 9,197
What's not working?

I ran your code and got 1 2 3 4 5 6 7 8 9 displayed, which is correct.
Apr 8 '17 #2

P: 56
If I am using *(*(arr+i)+j) instead of *((arr+i*n) + j) , then I am unable to get the correct OP , it shows error :
invalid type argument of 'unary *'

I am unable to get this .
Apr 8 '17 #3

P: 56
If I am using *(*(arr+i)+j) instead of *((arr+i*n) + j) , then I am unable to get the correct OP , it shows error :
invalid type argument of 'unary *'

I am unable to get this .
Apr 8 '17 #4

P: 56
If I am using *(*(arr+i)+j) instead of *((arr+i*n) + j) , then I am unable to get the correct OP , it shows error :
invalid type argument of 'unary *'

I am unable to get this .
Apr 8 '17 #5

weaknessforcats
Expert Mod 5K+
P: 9,197
You can't use this:

*(*(arr+i)+j)

because arr is an address so arr + i is also an address. But
*(arr + i) is an int. This makes *(arr+i) + j an int. Now you use another dereferencing * on an int so you get an error.
Apr 8 '17 #6

P: 56
Thanks , I got the point
Apr 9 '17 #7

P: 3
1) When both dimensions are available globally (either as a macro or as a global constant).

Expand|Select|Wrap|Line Numbers
  1. #include <stdio.h>
  2. const int M = 3;
  3. const int N = 3;
  4.  
  5. void print(int arr[M][N])
  6. {
  7.     int i, j;
  8.     for (i = 0; i < M; i++)
  9.       for (j = 0; j < N; j++)
  10.         printf("%d ", arr[i][j]);
  11. }
  12.  
  13. int main()
  14. {
  15.     int arr[][N] = {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}};
  16.     print(arr);
  17.     return 0;
  18. }
Run on IDE
Output:
Expand|Select|Wrap|Line Numbers
  1. 1 2 3 4 5 6 7 8 9
2) When only second dimension is available globally (either as a macro or as a global constant).

Expand|Select|Wrap|Line Numbers
  1. #include <stdio.h>
  2. const int N = 3;
  3.  
  4. void print(int arr[][N], int m)
  5. {
  6.     int i, j;
  7.     for (i = 0; i < m; i++)
  8.       for (j = 0; j < N; j++)
  9.         printf("%d ", arr[i][j]);
  10. }
  11.  
  12. int main()
  13. {
  14.     int arr[][3] = {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}};
  15.     print(arr, 3);
  16.     return 0;
  17. }
Run on IDE
Output:

Expand|Select|Wrap|Line Numbers
  1. 1 2 3 4 5 6 7 8 9
The above method is fine if second dimension is fixed and is not user specified. The following methods handle cases when second dimension can also change.

3) If compiler is C99 compatible
From C99, C language supports variable sized arrays to be passed simply by specifying the variable dimensions (See this for an example run)

Expand|Select|Wrap|Line Numbers
  1. // The following program works only if your compiler is C99 compatible.
  2. #include <stdio.h>
  3.  
  4. // n must be passed before the 2D array
  5. void print(int m, int n, int arr[][n])
  6. {
  7.     int i, j;
  8.     for (i = 0; i < m; i++)
  9.       for (j = 0; j < n; j++)
  10.         printf("%d ", arr[i][j]);
  11. }
  12.  
  13. int main()
  14. {
  15.     int arr[][3] = {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}};
  16.     int m = 3, n = 3;
  17.     print(m, n, arr);
  18.     return 0;
  19. }
Run on IDE
Output on a C99 compatible compiler:

Expand|Select|Wrap|Line Numbers
  1. 1 2 3 4 5 6 7 8 9
If compiler is not C99 compatible, then we can use one of the following methods to pass a variable sized 2D array.

4) Using a single pointer
In this method, we must typecast the 2D array when passing to function.

Expand|Select|Wrap|Line Numbers
  1. #include <stdio.h>
  2. void print(int *arr, int m, int n)
  3. {
  4.     int i, j;
  5.     for (i = 0; i < m; i++)
  6.       for (j = 0; j < n; j++)
  7.         printf("%d ", *((arr+i*n) + j));
  8. }
  9.  
  10. int main()
  11. {
  12.     int arr[][3] = {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}};
  13.     int m = 3, n = 3;
  14.  
  15.     // We can also use "print(&arr[0][0], m, n);"
  16.     print((int *)arr, m, n);
  17.     return 0;
  18. }
Run on IDE
Output:

Expand|Select|Wrap|Line Numbers
  1. 1 2 3 4 5 6 7 8 9
Apr 19 '17 #8

weaknessforcats
Expert Mod 5K+
P: 9,197
When you pass an argument to a function in C the argument is a copy of the variable used by the calling function. In the case of arrays, what is passed is the address of the array so the function in using that address operates on the original array that belongs to the calling function.

For this reason you cannot pass an array to a function.

What does happen is the function has a copy of the address of the array but has lost the dimensions so it has no idea how large the array is. This is called decay-of-array. True you can provide access to the dimensions by using variables from somewhere but there is no guarantee the values are accurate. If these values change in the called function, then the calling function has bad info and crashes. Any dimensional values must be passed (in C) by address.

If the array is on the stack and you pass the address to a function, that function can pass it anywhere else, save it to disc, etc. Then when the original function completes, the stack frame is deleted and all those saved copies of the array pointers now are invalid and when accessed will crash the program.

So addresses of arrays must be heap addresses which brings up memory allocations, leaks, reference counting whereby the array cannot be deleted until the last copy of the pointer is deleted.

etc.
etc.

This dire weakness of arrays in C is the main reason for the <vector> template in C++.
Apr 20 '17 #9

P: 56
Thanks a lot , I understood the concept now .
Apr 20 '17 #10

Post your reply

Sign in to post your reply or Sign up for a free account.