I use to program with FORTRAN, but I decided to learn C and C++. I started with C language, and the one thing that I never used are pointers, because FORTRAN pass values by reference. I built the sample code below to understand how pointers work with multidimensional arrays:
#include <stdio.h>
#include <stdlib.h>
#define DIM1 3
#define DIM2 2
#define DIM3 4
void display3DArray1(int, int , int n, int (*arr)[][n]);
void display3DArray2(int rows, int cols1, int cols2,int arr[][cols1][cols2]);
int main(void)
{
int matrix3D[DIM1][DIM2][DIM3] = {
{{1, 2, 3, 4}, {5, 6, 7, 8}},
{{9, 10, 11, 12}, {13, 14, 15, 16}},
{{17, 18, 19, 20}, {21, 22, 23, 24}}
};
int (*pmatrix3D)[DIM2][DIM3] = matrix3D;
display3DArray1(DIM1, DIM2, DIM3,pmatrix3D);
display3DArray2(DIM1, DIM2, DIM3,pmatrix3D);
return 0;
}
void display3DArray1(int rows, int cols1, int cols2,int (*arr)[][cols2]) {
printf("\n");
for(int i=0; i<rows; i++) {
for(int j=0; j<cols1; j++) {
for(int k=0; k<cols2; k++) {
printf("*arr : %d adress: %p\n",*(*((*arr+i*cols1))+j*cols2+k),*((*arr+i*cols1))+j*cols2+k);
}
}
}
}
void display3DArray2(int rows, int cols1, int cols2,int arr[][cols1][cols2]) {
printf("\n");
for(int i=0; i<rows; i++) {
for(int j=0; j<cols1; j++) {
for(int k=0; k<cols2; k++) {
printf("*arr : %d adress: %p\n", *(*(*(arr+i)+j) + k), *(*(arr+i)+j) + k) ;
}
}
}
}
The code works, but there is something that I wasn't able to understand. When I try to use the second printf of the second function in the first one I get a compilation error:
"invalid use of array with unspecified bounds" -- under gcc.
Why *(arr + i) doesn't work in the first function?
You can use the following two ways to pass/print the matrix:
void display3DArray1(int rows, int cols1, int cols2, int *A) {
int *a, i, j, k;
printf("\n");
for(i=0; i<rows; i++) {
for(j=0; j<cols1; j++) {
for(k=0; k<cols2; k++) {
a= A+(i*cols1*cols2)+(j*cols2)+k;
printf("%d, %p\n", *a, a);
}
}
}
}
void display3DArray2(int A[DIM1][DIM2][DIM3]) {
int i, j, k;
printf("\n");
for(i=0; i<DIM1; i++) {
for(j=0; j<DIM2; j++) {
for(k=0; k<DIM3; k++) {
printf("%d, %p\n", A[i][j][k], &A[i][j][k]);
}
}
}
}
The first method does not rely on the dimensions of the matrix; the second one does. As a result, the first one needs explicit address calculations (row i, col j, cell k).
Use calls respectively:
display3DArray1(DIM1, DIM2, DIM3, (int *)matrix3D);
display3DArray2(matrix3D);
Note the cast of the matrix to an int pointer.
In your code, you used parameter names to specify the dimensions of the matrix. In my C version, that is not legal; they must be constants.
Just a complement to Paul Ogilvie's answer.
The correct usage of Variable Length Arrays would be:
void display3DArray3(int rows, int cols1, int cols2,int arr[][cols1][cols2]) {
printf("\n");
for(int i=0; i<rows; i++) {
for(int j=0; j<cols1; j++) {
for(int k=0; k<cols2; k++) {
printf("*arr : %d adress: %p\n", arr[i][j][k], &arr[i][j][k]);
}
}
}
}
I was a bit puzzled, to be honest. The core issue is that the declaration of a function parameter like in f(T arr[]) declares an incomplete type whose size is not known (neither at compile time nor at run time). Originally I thought empty square brackets in function parameter declarations simply declare a pointer — notation notwithstanding —, but that is not the case. The parameter still has array type, albeit incomplete.1
When you write
void display3DArray1(int rows, int cols1, int cols2,int (*arr)[][cols2])
you declare a pointer to such an incomplete type of unknown size. This pointer cannot be manipulated in all the usual ways; in particular, adding to it in order to jump to the next element is impossible because we don't know where the current element ends (and hence the next element starts). But you try that in
printf("*arr : %d adress: %p\n", *(*(*(arr+i)+j) + k), *(*(arr+i)+j) + k) ;
with the innermost arr+1. Just dereferencing it works, because the variable holds the address of the first element all right. This is what the print in the first function does:
printf("*arr : %d adress: %p\n",*(*((*arr+i*cols1))+j*cols2+k),*((*arr+i*cols1))+j*cols2+k);
with *arr. The element size of the incomplete array to which arr points is known (these elements are arrays of cols2 ints), so that we can add to *arr, even if we can't add to arr proper.
For completeness: Why can you access arr that way in the second function? Well:
void display3DArray2(int rows, int cols1, int cols2,int arr[][cols1][cols2])
declares arr as an incomplete array type, true; but the size of its elements is well known: Those are cols1 x cols2 int matrices. The declaration just doesn't specify how many are there, but we can surely iterate them if we somehow know when to stop.
1 Of course this array, like any other, "decays" to a pointer in most contexts, so that the missing type information doesn't matter. But it matters if we have pointers to them.
I had trouble finding the correct syntax for dereferencing matrices of rank2 and rank3. The intent is to remove a level of indexing for faster execution. Here's some pseudo code that will get you started. This is more about getting the syntax right (MSVC 2019) than an example of working code.
int recurse(int n, unsigned char rank2[13][4], unsigned char rank3[13][4][13])
{
if (n < 13)
{
unsigned char (*deRefRank1)[4] = &rank2[n]; // deref matrix rank 2 to rank 1
unsigned char(*deRefRank2)[4][13] = &rank3[n]; // deref matrix rank 3 to 2
// insert pre-recurse code here ... use (*deRefRank1)[] and (*deRefRank2)[][]
if (recurse(n + 1, rank2[n], rank3[n])
return -1;
// insert post-recurse code here ...
}
return 0;
}
Your array indexing in the 'print' routines is invalid. The declaration of 'matrix3D' implies that the type of that name is 'pointer to int'. NOTE: Only one level of indirection there. The indexing expressions have a bunch of ''-s in front of terms; in C that means 'the item to the right of the '' is a pointer which must be dereferenced to get to the value'. That means you are in effect treating 'matrix3D' as 'pointer to (pointer to (pointer to int))' which is too many indirections.
Related
I have written code which allows me to modify the elements of a 1D array within my function by passing the element of the array:
I print the original array
I pass each element of the array to the function
Within the function I add the value 50 to each element of the array
I then call the function, and print out to screen the modified element value (i.e the value of each element +50)
I have been able to do this for a 1D array, with example values in the array being (10,20,30) and the valued printed after modification being (60,70,80).
What I am hoping to do is adapt that code to work for 2D arrays, you will see my attempt at doing this below. This code focuses on the use of int, but once I understand how to achieve this I am hoping to adapt for the use of a 2D string as well.
With the code below:
My objective is
Print to screen the original 2D array
Pass each element of the 2D array to the function
Within the function add the value 50 to each element of the array
Then call the function, and print out the modified element values to the screen(expected result displayed on screen 60,61,etc,.)
So far I have been able to print the original 2D array to the screen. It is the function I think I am messing up and would appreciate any advice. Thank you.
#include <stdio.h>
#include <string.h>
#define M 4
#define N 2
int function(int **arr);
int main() {
int i, a;
int arr[N][M] = {10, 11, 12, 13, 14, 15, 16, 17};
// the int array first
for(i = 0; i < N; i++) {
for(size_t j = 0; j < M; j++) {
// Accessing each variable
printf("value of arr[%d] is %d\n", i, arr[i][j]);
}
}
printf("\n ***values after modification***\n");
a = function(&arr[i][0]);
// int array print results
for(int i = 0; i < N; i++) {
for(size_t j = 0; j < M; j++) {
printf("value of arr %d\n", arr[i][j]);
}
}
return 0;
}
int function(int **arr) {
int i;
int j;
for(int i = 0; i < 3; i++) {
for(size_t j = 0; j < 5; j++) {
arr[i][j] = arr[i][j] + 50;
}
}
}
My apologies in advance for silly mistakes I am very new to C.
Thank you in advance.
The function int function(int **arr) does not return an int so make it void.
When you call it, a = function(&arr[i][0]);, you do not use a after the assignment. I suggest that you remove a from the program completely since it's not used anywhere.
The call to the function, function(&arr[i][0]);, should simply be function(arr);
The function signature needs to include the extent of all but the outermost dimension:
void function(int arr[][M])
Inside the function, you use 3 and 5 instead of N and M. That accesses the array out of bounds.
In function, the i and j you declare at the start of the function are unused. Remove them.
arr[i][j] = arr[i][j] + 50; is better written as arr[i][j] += 50;
When initializing a multidimensional array, use braces to make it simpler to read the code:
int arr[N][M] = {{10, 11, 12, 13}, {14, 15, 16, 17}};
In main you mix int and size_t for the indexing variables. I suggest you settle for one type.
Remove unused header files (string.h)
Example:
#include <stdio.h>
#define N 2
#define M 4
void function(int arr[][M]) {
for(int i = 0; i < N; i++) {
for(size_t j = 0; j < M; j++) {
arr[i][j] += 50;
}
}
}
int main() {
int arr[N][M] = {{10, 11, 12, 13}, {14, 15, 16, 17}};
for(size_t i = 0; i < N; i++) {
for(size_t j = 0; j < M; j++) {
printf("value of arr[%zu][%zu] is %d\n", i, j, arr[i][j]);
}
}
printf("\n ***values after modification***\n");
function(arr);
// int array print results
for(size_t i = 0; i < N; i++) {
for(size_t j = 0; j < M; j++) {
printf("value of arr[%zu][%zu] is %d\n", i, j, arr[i][j]);
}
}
}
Since you print the array more than once, you could also add a function to do so to not have to repeat that code in main:
void print(int arr[][M]) {
for(size_t i = 0; i < N; i++) {
for(size_t j = 0; j < M; j++) {
printf("value of arr[%zu][%zu] is %d\n", i, j, arr[i][j]);
}
}
}
Two-Dimensional arrays in C (and C++) are actually one-dimensional arrays whose elements are one-dimensional arrays. The indexing operator [] has left-to-right semantics, so for a type arr[N][M] the first index (with N elements) is evaluated first. The resulting expression, e.g. arr[0], the first element in arr, is a one-dimensional array with M elements. Of course that array can be indexed again , e.g. arr[0][1], resulting in the second int in the first sub-array.
One of the quirks in the C language is that if you use an array as a function argument, what the function sees is a pointer to the first element. An array used as an argument "decays" or, as the standard says, is "adjusted" that way. This is no different for two-dimensional arrays, except that the elements of a two-dimensional array are themselves arrays. Therefore, what the receiving function gets is a pointer to int arr[M].
Consider: If you want to pass a simple integer array, say intArr[3], to a function, what the function sees is a pointer to the first element. Such a function declaration might look like void f(int *intPtr) and for this example is simply called with f(intArr). An alternative way to write this is void f(int intPtr[]). It means exactly the same: The parameter is a pointer to an int, not an array. It is pointing to the first — maybe even only — element in a succession of ints.
The logic with 2-dimensional arrays is exactly the same — except that the elements, as discussed, have the type "array of M ints", e.g. int subArr[M]. A pointer argument to such a type can be written in two ways, like with the simple int array: As a pointer like void f(int (*subArrPtr)[M]) or in array notation with the number of top-level elements unknown, like void f(int arr[][M]). Like with the simple int array the two parameter notations are entirely equivalent and interchangeable. Both actually declare a pointer, so (*subArrPtr)[M] is, so to speak, more to the point(er) but perhaps more obscure.
The reason for the funny parentheses in (*subArrPtr)is that we must dereference the pointer first in order to obtain the actual array, and only then index that. Without the parentheses the indexing operator [] would have precedence. You can look up precedences in this table. [] is in group 1 with the highest priority while the dereferencing operator * (not the multiplication!) is in group 2. Without the parentheses we would index first and only then dereference the array element (which must therefore be a pointer), that is, we would declare an array of pointers instead of a pointer to an array.
The two possible, interchangeable signatures for your function therefore are
void function( int (*arrArg)[M] ); // pointer notation
void function( int arrArg[][M] ); // "array" notation (but actually a pointer)
The entire program, also correcting the problems Ted mentioned, and without printing the original values (we know them, after all), is below. I have also adapted the initialization of the two-dimensional array so that the sub-arrays become visible. C is very lenient with initializing structures and arrays; it simply lets you write consecutive values and fills the elements of nested subobjects as the come. But I think showing the structure helps understanding the code and also reveals mistakes, like having the wrong number of elements in the subarrays. I have declared the function one way and defined it the other way to show that the function signatures are equivalent. I also changed the names of the defines and of the function to give them more meaning.
#include<stdio.h>
#define NUM_ELEMS_SUBARRAY 4
#define NUM_ELEMS_ARRAY 2
/// #arrArg Is a pointer to the first in a row of one-dimensional
/// arrays with NUM_ELEMS_SUBARRAY ints each.
void add50ToElems(int arrArg[][NUM_ELEMS_SUBARRAY]);
int main()
{
// Show the nested structure of the 2-dimensional array.
int arr[NUM_ELEMS_ARRAY][NUM_ELEMS_SUBARRAY] =
{
{10, 11, 12, 13},
{14, 15, 16, 17}
};
// Modify the array
add50ToElems(arr);
// print results
for (int i = 0; i < NUM_ELEMS_ARRAY; i++) {
for (int j = 0; j < NUM_ELEMS_SUBARRAY; j++)
{
printf("value of arr[%d][%d]: %d\n", i, j, arr[i][j]);
}
}
return 0;
}
// Equivalent to declaration above
void add50ToElems(int (*arrArg)[NUM_ELEMS_SUBARRAY])
{
for (int i = 0; i < NUM_ELEMS_ARRAY; i++)
{
for (size_t j = 0; j < NUM_ELEMS_SUBARRAY; j++)
{
//arrArg[i][j] = arrArg[i][j] + 50;
arrArg[i][j] += 50; // more idiomatic
}
}
}
Why is it wrong to pass a two-dimensional array to a function expecting a pointer-to-pointer? Let's consider what void f(int *p) means. It receives a pointer to an int which often is the beginning of an array, that is, of a succession of ints lying one after the other in memory. For example
void f(int *p) { for(int i=0; i<3; ++i) { printf("%d ", p[i]); }
may be called with a pointer to the first element of an array:
static int arr[3];
void g() { f(arr); }
Of course this minimal example is unsafe (how does f know there are three ints?) but it serves the purpose.
So what would void f(int **p); mean? Analogously it is a pointer, pointing to the first in a succession of pointers which are lying one after the other in memory. We see already why this will spell disaster if we pass the address of a 2-dimensional array: The objects there are not pointers, but all ints! Consider:
int arr1[2] = { 1,2 };
int arr2[2] = { 2,3 };
int arr3[2] = { 3,4 };
// This array contains addresses which point
// to the first element in each of the above arrays.
int *arrOfPtrToStartOfArrays[3] // The array of pointers
= { arr1, arr2, arr3 }; // arrays decay to pointers
int **ptrToArrOfPtrs = arrOfPtrToStartOfArrays;
void f(int **pp)
{
for(int pi=0; pi<3; pi++) // iterate the pointers in the array
{
int *p = pp[pi]; // pp element is a pointer
// iterate through the ints starting at each address
// pointed to by pp[pi]
for(int i=0; i<2; i++) // two ints in each arr
{
printf("%d ", pp[pi][i]); // show double indexing of array of pointers
// Since pp[pi] is now p, we can also say:
printf("%d\n", p[i]); // index int pointer
}
}
}
int main()
{
f(ptrToArrOfPtrs);
}
f iterates through an array of pointers. It thinks that the value at that address, and at the subsequent addresses, are pointers! That is what the declaration int **pp means.
Now if we pass the address of an array full of ints instead, f will still think that the memory there is full of pointers. An expression like int *p = pp[i]; above will read an integer number (e.g., 1) and think it is an address. p[i] in the printf call will then attempt to access the memory at address 1.
Let's end with a discussion of why the idea that one should pass a 2-dimensional array as a pointer to a pointer is so common. One reason is that while declaring a 2-dimensional array argument as void f(int **arr); is dead wrong, you can access the first (but only the first) element of it with e.g. int i = **arr. The reason this works is that the first dereferencing gives you the first sub-array, to which you can in turn apply the dereferencing operator, yielding its first element. But if you pass the array as an argument to a function it does not decay to a pointer to a pointer, but instead, as discussed, to a pointer to its first element.
The second source of confusion is that accessing elements the array-of-pointers uses the same double-indexing as accessing elements in a true two-dimensional array: pp[pi][i] vs. arr[i][j]. But the code produced by these expressions is entirely different and spells disaster if the wrong type is passed. Your compiler warns about that, by the way.
I'm having some difficulties understanding two dimensional arrays in C.
Let's look at this example:
#include <stdio.h>
void foo(int arr[2][3]) {
printf("%d", *arr);
}
int main() {
int arr[2][3] = { {10, 20, 30},
{40, 50, 60}
};
foo(arr);
return 0;
}
I have a few questions:
What is the value of arr? Is it the address of arr[0][0]?
If arr is the address of arr[0][0], then why the line:
printf("%d", *arr);doesn't print the value 10?
Each time I run it, I get a strange number. what is the meaning of this number?
Thanks :)
In answer to your questions:
Used in an expression, the value of arr is a pointer to its first element. Since it's an array of arrays, the pointer to its first element is &arr[0]. This value has an unusual type, "pointer to array of 3 ints".
Because arr is not the address of arr[0][0].
This is a crazy situation, hard to understand and hard to explain. In brief: since arr is a pointer to an array, *arr is that array. But when you try to pass it to printf, the compiler turns around and generates a pointer to the array's first element again. I suspect that pointer value differs because your compiler and OS are putting main (and therefore arr) in a different place on the stack each time. (And then there's the additional problem that since we're talking about pointers, it doesn't necessarily work to print them %d, especially if your machine has 32-bit ints and 64-bit pointers.)
My advice to you is not to worry about why the incorrect code printed changing values. Rather, please just print the array correctly, with code like this:
int i, j;
for(i = 0; i < 2; i++) {
for(j = 0; j < 3; j++)
printf("%d ", arr[i][j]);
printf("\n");
}
It is possible by doing like this:
#include <stdio.h>
int main()
{
int arr[2][2] = {{2,3},{5,6}};
for (int i = 0; i < 2; i++) {
for (int j = 0;j < 2; j++) {
printf("%d\n" , *(&arr[i][j]));
}
}
}
I am trying to fill a 2d array in function drawInitialNim(), using values passed from main.
int drawInitialBoard(int x, int y, int z);
int main(int argc, const char * argv[]) {
int board[3][50] = {{0}};
int row1, row2, row3;
int i, j;
row1 = 0;
row2 = 0;
row3 = 0;
printf("Enter the number of rocks in each row: ");
scanf("%d %d %d", &row1, &row2, &row3); //values for amount of "O" in the array
printf("this is row 1: %d\n", row1); //debug
board[2][49] = drawInitialBoard(row1, row2, row3); //fill array from function
printf("this is 0,0 in main: %d\n",board[0][0]); // debug
for (i=0; i<3; i++) { //print indexes that contain "O" or 79
printf("Row %d: ", i+1);
for (j=0; j<50; j++) {
if (board[i][j] != 0) {
printf("%c", board[i][j]);
}
}
printf("\n");
}
}
int drawInitialBoard(int x, int y, int z)
{
int i,j,k;
static int arr[3][50] = {{0}};
for (i=0; i<x; i++) { //fill board with "O", or its that equal 79
arr[0][i] = 'O';
}
for (j=0; j<y; j++) {
arr[1][j] = 'O';
}
for (k=0; k<z; k++) {
arr[2][k] = 'O';
}
printf("This is 0,0 in the function: %d\n", arr[0][0]); //debug
return **arr;
}
I am getting this output, using 1, 2, 3 as input for x, y, z in main:
Row 1:
Row 2:
Row 3: O
I feel like the values from drawInitialNim() are not getting passed to main properly. I know that arrays can't be returned, so I returned the pointer. Additionally, I don't think that this is a dereferencing problem. I am not sure how to solve this.
Any help would be appreciated!
See the first thing I see incorrect in your program is:
You define the function like int drawInitialBoard(int x, int y, int z); which means that it will give back an int but you are returning **arr. Now according to what I know, * means "value at address of" so *arr would mean value at address of the pointer arr. And as arr is an array it is a pointer to its first element. So I think there is something wrong in there when you use return **arr. And as the first element in the array is not a pointer then I think that **arr would probably just give you not what you desire.
Your function is declaring an array, filling the rows according to the arguments passed, and then returning the value of arr[0][0], which in the case of the input values you state is 79 or 'O'. This value is then written to the main array board[2][49] and you then report correctly on its contents - all other elements are still 0. I don't see why you are using two arrays, not just one. And I don't see why you have declared an int array when you are treating it as a char array.
An easier way to make you program work would be, make your array board[3][50] global.
And, change the return type of your function drawInitialBoard(int x, int y, int z); to void, i.e., void drawInitialBoard(int x, int y, int z);.
And instead of working on a new array arr in the function, you can use the array defined previously board[3][50].
This won't clear the concept of passing the 2-D array, but will surely make it work.
How do I write a function to search for an element in two dimensional array: if exists returns 1, otherwise returns no?
#include <stdio.h>
int search(int a[3][3],int x);
int main ()
{
int Array[3][3]; // array of size 3*3
int i,j; //counters i,j
int result,number;
for(i=0;i<3;i++)
{
printf("\n");
for(j=0;j<3;j++)
{
printf(" Array[%d][%d]= ",i,j);
scanf("%d", &Array[i][j]); //Fill The 3*3 array
}
}
printf("Enter The number you want:>");
scanf("%d",&number);
result=search(Array,number);
if(search(Array,number))
printf("Number exists\n");
else
printf("Number does not exists\n");
return 0;
}
int search(int a[3][3],int x){
int i,j;
for(i=0;i<3;i++){
for(j=0;j<3;j++){
if (x==a[i][j])
return 1;
return 0;
}
}
}
is this right ??
No, it's not. You need to move the return 0; out of the two for loops, and have it be the last statement in search.
No. The return 0; statement should be placed on the line before the very last closing brace.
Your program is not running because the search algorithm returns 1 if and only if the search element is in array[0][0], otherwise it returns zero and you think that the element doesn't exists. All you need to do is return 0 after traversing the full multi-dimensional array.
You can look into above answers. They have given good solutions.
No because your return 0; is inside the for loops.
I think what you want is that :
#include <stdio.h>
int search(int a[3][3],int x);
int main ()
{
int Array[3][3]; // array of size 3*3
int i,j; //counters i,j
int result,number;
for(i=0;i<3;i++)
{ printf("\n");
for(j=0;j<3;j++)
{
printf(" Array[%d][%d]= ",i,j);
scanf("%d", &Array[i][j]); //Fill The 3*3 array
}
}
printf("Enter The number you want:>");
scanf("%d",&number);
result=search(Array,number);
if(result)
printf("Number exists\n");
else
printf("Number does not exists\n");
return 0;
}
int search(int a[3][3],int x)
{
int i,j;
for(i=0;i<3;i++)
{
for(j=0;j<3;j++)
{
if (x==a[i][j])
return 1;
}
}
return 0;
}
Jon gave you the answer you need, but there are some details to be aware of.
C's treatment of arrays is such that the search function doesn't receive a 3x3 array of int; rather, it receives a pointer to a 3-element array of int. From the C language standard, draft n1256:
6.3.2.1 Lvalues, arrays, and function designators
...
3 Except when it is the operand of the sizeof operator or the unary & operator, or is a string literal used to initialize an array, an expression that has type ‘‘array of type’’ is converted to an expression with type ‘‘pointer to type’’ that points to the initial element of the array object and is not an lvalue. If the array object has register storage class, the behavior is undefined.
Thus, when you call result = search(Array, number);, the type of the expression Array is implicitly converted from a 3-element array of 3-element arrays of int (int [3][3]) to a pointer to a 3-element array of int (int (*)[3]). In the context of a function parameter declaration, T a[] and T a[n] are synonymous with T *a. You could change the function prototype to
int search(int (*a)[3], int x)
and it would behave exactly the same.
One consequence of this is that search can operate not just on 3x3 arrays, but on any Nx3 array. You've written your function to assume that a is always 3x3; if you want to be able to handle arrays of different numbers of rows, you would need to pass in a separate parameter to specify the number of rows in the array:
int search(int (*a)[3], size_t rows, int x)
{
size_t i, j;
for (i = 0; i < rows; i++)
for (j = 0; j < 3; j++)
if (a[i][j] == x)
return 1;
return 0;
}
int main(void)
{
int fiveRowArray[5][3] = {{ 1, 2, 3}, { 4, 5, 6}, { 7, 8, 9},
{10,11,12}, {13,14,15}};
int twoRowArray[2][3] = {{ 1, 2, 3}, { 4, 5, 6}};
int number;
printf("Gimme a number: ");
fflush(stdout);
scanf("%d", &number);
if (search(array, sizeof fiveRowArray / sizeof *fiveRowArray, number))
printf("Number exists in fiveRowArray\n");
else
printf("Number does not exist in fiveRowArray\n");
if (search(array, sizeof twoRowArray / sizeof *twoRowArray , number))
printf("Number exists in twoRowArray \n");
else
printf("Number does not exist in twoRowArray \n");
return 0;
}
The sizeof arr / sizeof *arr expression calculates the number of elements in the array by getting the total array size in bytes (sizeof arr) and dividing that by the number of bytes in an individual array element (sizeof *arr or sizeof arr[0]). Note that this only works for expressions of array type; it will not work for pointers that are being treated as arrays (such as the expression a in the search function).
If you want to handle different numbers of rows and columns, you'll have to take a different approach:
int search(int *a, size_t rows, size_t cols, int x)
{
size_t i, j;
for (i = 0; i < rows; i++)
for (j = 0; j < cols; j++)
if (a[i * cols + j] == x)
return 1;
return 0;
}
int main(void)
{
int fiveByThree[5][3] = {...};
int twoByFour[2][4] = {...};
...
if (search(&fiveByThree[0][0],
sizeof fiveByThree / sizeof *fiveByThree,
sizeof fiveByThree[0] / sizeof *fiveByThree[0],
number))
...
if (search(&twoByFour[0][0],
sizeof twoByFour / sizeof *twoByFour,
sizeof twoByFour[0] / sizeof *twoByFour[0],
number))
...
}
In this case, we explicitly pass a pointer to the first element in each array, so instead of receiving a pointer to an array of int, search receives a simple pointer to int, which we treat as a 1D array, and compute the offset manually as i * cols + j. This code assumes that all elements in the 2D array are contiguous.
Edit
Note that in C99, you can have what are called Variable Length Arrays (VLAs), where the array dimension can be specified by a runtime variable rather than a constant expression; this allows us to write the prototype as
int search(size_t rows, size_t cols, int arr[rows][cols], int x)
and not mess with pointers.
Consider this code:
#include <stdio.h>
#define N 5
void printMatrix(int (*matrix)[N],int n)
{
int i,j;
for(i=0;i<n;i++){
for(j=0;j<n;j++)
printf("%d",matrix[i][j]);
printf("\n");
}
}
int main()
{
int R[N][N]={{1,2,3},{4,5,6},{7,8,9}};
printMatrix(R,3);
}
This works fine as expected.
Now, I thought to write the functions handling 2D-matrices in a separate source file and link them wherever required.
But then I ran into a problem as in the function printMatrix, the size of array of int to which matrix points (i.e N) is required at compile-time. So, my functions would not work in other cases when the size is different.
So,How can I handle this?
Dynamic Arrays are a solution but i want to know if it can be done with static arrays.
You can't use the built-in 2D array type if both sizes are not known at compile time. A built-in 2D array must have at least one of the two sizes known at compile time.
If both sizes are run-time values, then you have no other choice but to use a "manual" implementation of 2D array, like an array of pointers to arrays, for example. In that case the function declaration might look as follows (two alternative equivalent forms)
void printMatrix(int *const *matrix, int n, int m);
void printMatrix(int *const matrix[], int n, int m);
To access to the array elements you can still use the "traditional" syntax
matrix[i][j]
The array itself would be created as follows (a simple example)
int row0[] = { 1, 2, 3 };
int row1[] = { 4, 5, 6 };
int *matrix[2];
matrix[0] = row0;
matrix[1] = row1;
printMatrix(matrix, 2, 3);
But if you already have a matrix implemented as a built-in 2d array
int matrix[2][3] = { ... };
then just to be able to pass it to the above function you can "convert" it into the above form by using an additional temporary "row pointer" array
int *rows[2];
rows[0] = matrix[0];
rows[1] = matrix[1];
printMatrix(rows, 2, 3);
Write yourself a macro:
#define MAT(i,j) matrix[i*n + j];
and declare "matrix" as a simple pointer to an "int".
Calculate the array index yourself. This will handle an arbitrary two dimensional array, for example:
void printMatrix(int *matrix,int n, int m)
{
int i,j;
for(i=0;i<n;i++){
for(j=0;j<m;j++)
printf("%d",matrix[m * i + j]);
printf("\n");
}
}
Don't try to pass it as a 2-D array; pass a pointer to the first element, then compute offsets manually:
void printMatrix(int *a, size_t m, size_t n)
{
size_t i,j;
for (i = 0; i < m; i++)
{
for (j = 0; j < n; j++)
{
printf("a[%lu][%lu] = %d\n",
(unsigned long) i,
(unsigned long) j,
a[i*n+j]); // treat a as 1-d array, compute offset manually
}
}
}
int main(void)
{
int arr[5][4];
...
printMatrix(&arr[0][0], 5, 4);
...
}
Granted, this will only work for contiguously allocated arrays.
Although the syntax is not exactly the same, but this also happens to work a bit:
#include <stdio.h>
#define N 5
void printMatrix(int* row,int n,int sz)
{
int i,j;
int *currRow;
for(i=0;i<n;i++){
currRow = row+i*sz;
for(j=0;j<n;j++)
printf("%d",currRow[j]);
printf("\n");
}
}
int main()
{
int R[N][N]={{1,2,3},{4,5,6},{7,8,9}};
printMatrix(R[0],3,sizeof(R[0])/sizeof(int));
}