I am having trouble passing a pointer array to a function. I will post a simple example that still doesn't work for me. Could you please tell me what I am doing wrong?
#include <stdio.h>
#include <stdlib.h>
int transformare(int *v[1])
{
*v[1] = 10;
return 0;
}
int main()
{
int v[1];
printf("n = ");
scanf("%d", &v[1]);
transformare(&v);
printf("%d", v[1]);
return 0;
}
You have two problems:
Array indexes are zero-based. That is, an array of N elements have indexes from 0 to N - 1 (inclusive)
The declaration int *v[1] declares v as an array of one pointer to int, not as a pointer to an array of one int. That would be int (*v)[1]. Which is also the type of &v from the main function.
The solution to the second problem (using the correct type) then leads to a third problem, as it means that *v[0] is incorrect due to operator precedence. You need to use parentheses here too, as in (*v)[0].
However the second (and the following third) problem is moot, since you don't need to pass arrays "by reference".
Arrays naturally decays to pointers to their first element. When using plain v when a pointer to int is expected, the compiler will automatically translate it as &v[0].
That means you could declare the function to simply take an int * as argument, and simply pass plain v as the argument.
First, please note that indizes are 0-based in C, i.e. the first (and - in your case only) element is v[0].
Concerning passing it, just define the parameter as pointer to int, i.e. int*. A variable of type int[1] will decay to a pointer to int when passed to a function (so there is no need to write transformare(&v), its transformare(v).
int transformare(int *v)
{
v[0] = 10;
return 0;
}
int main()
{
int v[1];
printf("n = ");
scanf("%d", &v[0]);
transformare(v);
printf("%d", v[0]);
return 0;
}
Related
I will show the entire code, but look for the quotes above the pointers as I will be talking about my problem there. I will tell you what I think happened there at the quote comments. The code compiles and runs, I just need help understanding parts of the code.
#include <stdio.h>
#include <stdlib.h>
int *get_data(int num_grades);
float calc_average(int num_grades, int grades[]);
void display_average(float ave);
int main()
{
int num_grades = 10;
const int MAX_GRADE = 100;
Below this quote box at: int *result = get_data(num_grades);
I have a pretty simple understanding of pointers at this point, as I've been introduced to them recently, however I can't seem to wrap my head around what happens when you assign a function to a pointer. What I think should happen is that the pointer int *result should be pointing at an address. Instead its pointing to a function that is also a pointer i think. So is this a pointer to a pointer at: int *result = get_data(num_grades); ?
I will put the rest of my question at the get_data function below.
int *result = get_data(num_grades);
^ Above ^
if (num_grades ==0)
printf("no grades to average\n");
else
{
float ave = calc_average(num_grades, result);
display_average(ave);
}
free(result);
return 0;
}
float calc_average(int num_grades, int grades[])
{
float ave;
int i;
int sum = 0;
for (i = 0; i < num_grades; i++)
{
sum+=grades[i];
}
ave = (float)sum/num_grades;
return ave;
}
void display_average(float ave)
{
printf("average: %.2f\n", ave);
}
Below this quote box,
I think this is a function pointer that returns a int pointer?
So, inside the body of the function, we create a new pointer, allocate memory for it, assign grades for each 'pointee' i think, and then I'm not sure why a[i] = grade is working, what are these indexes coming from, I don't understand why this is working if there is no array declared. Can someone explain what is happening here? How does this work? I'm really confused here.
int *get_data(int num_grades)
{
int* a;
a = malloc(num_grades * sizeof(int));
int i;
for (i = 0; i < num_grades; i++)
{
printf("enter a grade: ");
int grade;
scanf("%d", &grade);
if(grade<=100)
{
a[i] = grade;
}
else
{
printf("grade needs to be > 0 and <= 100\n");
i--;
}
}
return a;
^ Above, this whole function ^
}
get_data is a function which returns a pointer to an integer. First of all:
int *result = get_data(num_grades);
in this line you are not assigning to result a pointer to function, but the result of the function being called with num_grades as argument. That is to say, to the a you calculated in the body of get_data. And after that:
int *get_data(int num_grades)
this is the declaration of a function called get_data which takes one int parameter and returns a pointer to int. You could rearrange the spaces like this:
int* get_data(int num_grades)
if it makes things clearer. In this context, saying that get_data is a pointer to function would not even make sense, since it's immediately followed by its body. For reference:
int (*get_data)(int num_grades);
this is how the declaration of a pointer to function taking one int param and returning an int looks like. And there can't be a function body after it.
... however I can't seem to wrap my head around what happens when you assign a function to a pointer.
You aren't assigning a function to a pointer; you're assigning the return value of the function (which happens to be an int * value) to a variable which happens to store int * values.
So is this a pointer to a pointer at: int *result = get_data(num_grades); ?
No. int * means 'pointer to int'.
I think this is a function pointer that returns a int pointer?
No. The function returns an int * (pointer to int). There is a function pointer in your code, though that isn't a function (because it's a function pointer) and it doesn't return anything (because it's not a function; it's a function pointer).
Remember, int * means 'pointer to int'.
and then I'm not sure why a[i] = grade is working, what are these indexes coming from, I don't understand why this is working if there is no array declared. Can someone explain what is happening here? How does this work? I'm really confused here.
The array[index] operator is actually a pointer[index] operator. It's syntactic sugar for *(array + index) or *(pointer + index).
Whenever an expression that has an array type is used (with the exception being taking the sizeof or &addressof an array), the expression is converted to a pointer. The pointer points to the first item of the array...
So whilst your pointer declaration will have different semantics for the sizeof and &addressof operators, it'll have the same semantics for the 'array subscript' operator.
A similar concept applies to functions (hence the "function pointer" explanation above). Technically, in your expression int *result = get_data(num_grades); you're not applying the function(argument) operator; you're applying the function_pointer(argument) operator. The expression denoting the function is converted to a function pointer...
I understand it is not possible to pass an array to a function in C and modify it without using sending a reference to that array, so how is the chess method initialising the array, and it is being printed correctly in main?
int chess(int rows, int cols, int array[rows][cols])
{
/* Go through the rows and colums in the array */
for (int i = 0; i < rows;i++)
{
for (int j = 0; j < cols; j++)
{
/* If the location is even, then print a 0, else print a 1. */
if (((i + j) % 2) ==0)
{
array[i][j] = 0;
}
else
{
array[i][j] = 1;
}
}
}
/* return */
return 0;
}
int main(void)
{
int arrayDimensions;
int noOfTests = 7;
/* run the program for the given amount of tests */
/*for (arrayDimensions = 0; arrayDimensions <= noOfTests; arrayDimensions++)*/
{
/* Declare an array for each dimension */
int array[6][5];
/* call the chess method passing it the arguments specified. */
chess(6, 5, array);
/* Print out the array according to the size of the array. */
for (int i = 0; i < 6; i++)
{
printf("\n");
for (int j = 0; j < 5; j++)
{
printf("%d", array[i][j]);
}
}
/* Create a new line after each row */
printf("\n");
}
}
Though you probably already know most of this, the latter part is relevant, so stay with this for a moment.
What you probably know
C is a pass-by-value language. This means when you do this:
void foo(int x)
{
x = 5;
}
called as
int n = 1;
foo(n);
printf("%d\n", n); // n is still 1
the caller passes a value and the parameter x receives it. But changing x has no effect on the caller. If you want to modify a caller's data variable, you must do so by-address. You do this by declaring the formal parameter to be a pointer-to-type, dereference the pointer to modify the pointed-to data, and finally, pass the address of the variable to modify:
void foo(int *p)
{
*p = 5;
}
called as:
int n = 1;
foo(&n);
printf("%d\n", n); // n is now 5
Why do you care?
So what does any of this have to do with your array? Arrays in C are a contiguous sequence of data of the underlying type of the array, and an array's expression value is the address of its first element.
Chew on that last sentence for a minute. That means the same way an int variable has a value of the int stored within, an array variables has the address of its first element as its "value". By now you know that pointers hold addresses. Knowing that and the previous description means this:
int ar[10];
int *p = ar;
is legal. The "value" of ar is its first-element address, and we're assigning that address to p, a pointer.
Ok then, So the language specifically defined arrays as parameters as simply pointers to their first elements. Therefore both of these are equivalent:
void foo(int *p)
{
*p = 5;
}
void bar(int ar[])
{
ar[0] = 5;
}
And the caller side:
int ar[10];
foo(ar); // legal, ar's "value" is its first element address
bar(ar); // legal, identical to the above.
A phrase I often use when explaining the fundamentals of pointers and arrays is simply this:
A pointer is a variable that holds an address; an array is a variable that is an address.
So whats with this whacky syntax?
int chess(int rows, int cols, int array[rows][cols])
Ah. There is something interesting. Your compiler supports VLA s (variable length arrays). When compiling the code for this function the compiler generates the proper logic to perform the proper access to the passed array. I.e. it knows that this:
array[1][0]
is cols many int values past the beginning of the array. Without the feature of VLAs (and some C compilers don't have them), you would have to do this row-by-column math yourself by hand. Not impossible, but tedious none-the-lesss. And i only briefly mention that C++ doesn't support VLA's; one of the few features C has that C++ does not.
Summary
Arrays are passed by address because when it comes to their "value", that is all they really are: an address.
Note: I worked very hard to avoid using the word "decay" or the phrase "decays to a pointer" in this description precisely because that verb implies some mystical functional operation when in-fact none exists. Arrays don't "decay" to anything. They simply are; Their "value", per the C standard, is the address of their first element. Period. What you do with that address is another matter. And as an address, a pointer can hold their "value" and dereference to access said-same (such as a function parameter).
Personal: I once asked on this forum how long that term (decay) has been buzzed about in C-engineer vernacular, since in the 600+ pages of the C standard it appears exactly ZERO times. The farthest back anyone found was 1988 in the annals of some conspicuous online journal. I'm always curious to note who started it an where, and said-quest continues to elude me.
Anyway, I hope this helps, even a little.
when dealing with arrays you are dealing with an address so if you pass an array into a function and you changed the array in the function, the real array will change.
In other words, if you know pointers an array is a pointer.
I didn't read the code but you have a clear misunderstanding of passing an array to a function.
An array reference IS an address (it's a misnomer to say it's a pointer, but it will behave as such). It works because the function is declared to accept a type of int[][], which allows the function to interact with the array reference as if you'd passed a pointer to the function.
From a reference manual:
When a function parameter is declared as an array, the compiler treats
the declaration as a pointer to the first element of the array. For
example, if x is a parameter and is intended to represent an array of
integers, it can be declared as any one of the following declarations:
int x[]; int *x; int x[10];
So you are passing a reference. The compiler turns your declaration into a pointer reference with also some sizing constraints.
I am getting an error in the return line. "Incompatible pointer to integer conversion returning 'int (*)[2]' from a function with result type 'int'" can someone explain what is theory behind this error and how to fix it? still I am getting right result, but don't know about this error. (hints: I am very beginner )
here is my testing code.
#include <stdio.h>
#include<string.h>
/* two diminsanl array testing*/
int array_function(int phase,int array[][2]);
int main()
{
int phase =1;
int array[][2]={};
array_function(phase, array);
phase =2;
array_function(phase, array);
return 0;
}
int array_function(int phase, int array[][2])
{
if(phase==1)
{
array[0][0]=1;
array[0][1]=2;
array[1][0]=3;
array[1][1]=4;
}
if(phase==2)
{
printf("%d\n",array[0][0]);
}
return array; //<------------- error line
}
Well, first of all, your function is expecting an int return, but you're trying to return an int[][].
And, you can't return an array by value in c. You'll need to return a pointer, or wrap the array as part of a struct.
You have int as return type of function ( int array_function() ) but are trying to return a pointer(return array;). Since it look that you don't need to return anything just have the return type as void or return 0. Since array is passed by reference it automatically gets the changes that you do to it inside the function.
If you statically create an array you have to specify both dimensions.
Arrays are passed as pointers and if you pass a static array it is good practice to give the dimensions in the parameters of the function. Simply pass the arrays name to any function even if you allocated it dynamically. If you want to return an array you should return an int* or int** for a 2D array.
Let's say you want to create an array in a function and let the caller have it.
int *createArray(int size)
{
int *array = malloc(size * sizeof(int));
return array;
}
You can call this function from your main.
int *list;
list = createArray(2);
And modify list like any other array.
This is your code properly.
#include <stdio.h>
/* two diminsanl array testing*/
void array_function(int phase, int array[2][2]);
int main()
{
int phase = 1;
int array[2][2];
array_function(phase, array);
phase = 2;
array_function(phase, array);
return 0;
}
void array_function(int phase, int array[2][2])
{
if (phase == 1)
{
array[0][0] = 1;
array[0][1] = 2;
array[1][0] = 3;
array[1][1] = 4;
}
if (phase == 2)
{
printf("%d\n",array[0][0]);
}
}
First this line, is not a legal assignment:
int array[][2]={};
For what you are doing, this line would work:
int array[][2]={0,0,0,0};
second As others have pointed out, this line is attempting to return int[][]. Two problems with this, 1) C cannot return the value representation of an array of ints, (although it can return pointers, such as int **, you don't need to here. See note at bottom). And 2) the prototype clearly calls for int
return array; //<------------- error line
For now, simply change the line to:
return 0;
Those two changes will result in your code populating array[][] with no errors.
Note: because you are passing your array by reference, ( array_function(phase, array); ) the values assigned to array within array_function() are made available back in the main() function without having them returned as a return. (i.e. int ** array_function(phase, array) )
So, first of all, the type of the expression array in array_function is int (*)[2], or "pointer to 2-element array of int".
Except when it is the operand of the sizeof or unary & operator, or is a string literal being used to initialize another array in a declaration, an expression of type "N-element array of T" will be converted ("decay") to an expression of type "pointer to T", and the value of the expression will be the address of the first element of the array.
When you call phase_array from main, like so:
array_function(phase, array);
the expression array has type "2-element array of 2-element array of int"; since it is not the operand of the sizeof or unary & operators, it is converted to an expression of type "pointer to 2-element array of int", and its value is set to the address of the first element (&array[0]). This pointer value is what gets passed to array_function.
In the context of a function parameter list, declarations of the forms T a[N] and T a[] will be interpreted as T *a; all three declare a as a pointer to T. So,
int array_function(int phase, int array[][2])
is the same as
int array_function(int phase, int (*array)[2])
Which brings us to your error message: you've declared array_function to return an int (which you don't ever use in your main function, btw), but the type of the expression array is int (*)[2]; hence the error message. The two types are not *compatible", and the compiler flags this as an error.
Since you've passed the address of the first element of array to array_function, any changes you make to the array contents will be reflected in main, so you really don't need to return the array. As others have suggested, just change the type of the function to void and don't return anything.
I had to write a program which has a function that sums all positive number in an array, but using function parameter array as an pointer. There in main function a problem occurs, when i try to call sum function. here is my source code:
#include <stdio.h>
#include <conio.h>
int posit(int *x[], int n){
int s=0;
for(int i=0; i<n; i++){
if(*x[i]>0){
s=s+*x[i];
}
}
return s;
}
int main(){
int k;
scanf("%d",&k);
int a[k];
for(int i=0; i<k; i++){
scanf("%d",&a[i]);
}
int b=posit(&a,k);
printf("%d\n", b);
getch();
return 0;
}
When an array is passed to a function it decays to a pointer to its first element. Change the signature of the function to:
int posit(int* x, int n){ /* Equivalent to 'int posit(int x[], int n)' */
and change the element access syntax of the array in the function from *x[i] to just x[i]. The invoke the function:
int b=posit(a,k);
Another point worth mentioning is to check the return value of scanf(), which returns the number of assignments made, to ensure &a[i] is actually being assigned and the program is subsequently not using uninitialized variables.
You may find the Arrays and Pointers section of the C FAQ useful.
Actually in your example you are passing to function pointer to pointer (please note that similar notation is very often used with main argument char *argv[]).
As mentioned in hmjd post while passing array to function this is converted to address of its first element. Instead of explicitly using pointer (int *x) you can also use array notation (int[] or even int[k]) but those are the same.
Please also note that in second method (int[k]) size provided doesn't matter and inside function it will be not known. This is only important to include size when you are dealing with multiple dimension arrays, but this is other story...
From K&R2
When an array name is passed to a function, what is passed is the
location of the initial element. Within the called function, this
argument is a local variable, and so an array name parameter is a
pointer, that is, a variable containing an address.
So you will be passing only the first element to the function.
Once this is understood your source can be modified as follows
int posit(int *x, int n)
and to call this function from main you can use
int b=posit(a,k); //Note only the location of the first element is being passed
The compiler shows:
Warning: passing argument 1 of 'fun' from incompatible
pointer type; note: expected 'int ()[5]' but argument
is of type 'int (*)[5][5]'
Code:
#include<stdio.h>
void fun(int * b[][5])
{
int x=11,y=90;
printf("here");
*b[1][3] = x;
*b[3][1] = y;
*b[2][2] = x + ++y;
}
int main()
{
int a[5][5];
a[1][3] = 12;
a[3][1] = 145;
fun(&a);
printf("%d %d %d",a[1][3],a[3][1],a[2][2]);
}
You do not need the asterisk in your function parameters, and you don't need to dereference the array b in your function. Arrays are passed by reference (so get rid of the ampersand in foo(&a) as well), because C treats them as pointers to the first element in the sequence.
Multidimensional arrays are treated as arrays of pointers to the start of smaller sub-arrays, i.e. arrays-of-arrays. Same explanation as above applies.
Your code should look like this in the end:
void fun(int b[][5]) // can also be (int (*b)[5]), i.e. array of 5 pointers
{
int x=11,y=90;
b[1][3] = x;
b[3][1] = y;
b[2][2] = x + ++y;
}
int main()
{ // ...
fun(a);
// ...
}
int a[5][5]; //is an 2d int array
When arrays are passed to a function, what really gets passed is a pointer to the arrays first element.
So calling the fun() function with fun(a) will actually pass the pointer to the a first element, in this case an int array of size 5. The function fun() will receive a pointer to an int array of size 5, that is to say int (*b)[5]. Note that int *b[5] is not the same and is an array of size 5 containing int pointers.
Your fun function can either have:
void fun(int b[][5])
or
void fun(int (*b)[5])
The first way to do it says that the function will receive a 2d array of ints, but since we know that what actually will be sent to the function is a pointer to the first element of the array a, the compiler will quietly compile the function as if the parameter were a pointer, since it's a pointer that it will receive.
The second way to do it explicitly shows what type it will receive, a pointer to an array of size 5.