# Thread: Pointers as Arguments in Functions

1. ## Pointers as Arguments in Functions

Hi,

I'm having some problems with a function. The function is supposed to find the two largest values in an array.

Code:
```void find_two_largest( const int *a, int n, int *largest, int *second_largest){
largest = a;
int temp;
second_largest = a;
for ( int i = 1; i < n; i++){
if (*(a + i) > *largest){
temp = *largest;
*largest = *(a + i);
*second_largest = temp;
}
else if (*(a+i) > *second_largest)
*second_largest = *(a+i);

}
}```
I don't see any mistake with the code of the function, but when I try to call it inside my program it only returns 0 for both largest and second_largest.

Code:
```int *find_middle( int *a, int n);

void find_two_largest(const int *a, int n, int *largest, int *second_largest);

int main()
{
int n;
printf("No. of elements?");
scanf("%d",&n);
int a[n];
printf("Elements of array:");
for (int i=0; i<n; i++)
scanf("%d", &a[i]);
int largest, second_largest;
find_two_largest(a, n, &largest, &second_largest);
printf("Largest element is %d, second largest is %d", largest, second_largest);
}```
Can someone tell me what I'm doing wrong. Do I have to declare the variables largest and second_largest as normal integer variables and then pass their addresses as arguments to find_largest or is that incorrect? 2. Line 2 and 4 obviously don't do what you think they should do.

Compare them to line 8

If you have such a problem with pointer notation - use array notation + temporary variable inside your function to store the intermediate results.

After your search is done - assign the found data to output parameters.

Another benefit with this approach - you can pass NULL to one of the output parameters and your function could verify it before final assignment and skip on it if the caller is interested to know one of them and not the both. 3. The compiler gives no warnings when compiling this code? 4. Originally Posted by vart Line 2 and 4 obviously don't do what you think they should do.

Compare them to line 8

If you have such a problem with pointer notation - use array notation + temporary variable inside your function to store the intermediate results.

After your search is done - assign the found data to output parameters.

Another benefit with this approach - you can pass NULL to one of the output parameters and your function could verify it before final assignment and skip on it if the caller is interested to know one of them and not the both.

I thought that largest=a and second_largest=a would assign the address of the first element of the array to both pointer variables. Is that incorrect? I learned that array names can be used as a pointer to its first element and both largest and second_largest are pointer variables, so that assignment should be legal. *largest and *second_largest should then give the values of the first element. During the loop the elements of the array, *(a+i) that is, are then assigned to *largest depending on whether the conditions hold.

From what I've read about pointers, they simply contain the address of the variable they are pointing to and after assigning a pointer variable to a variable the two are basically "equivalent", in the sense that if I change the value of one of the two, the other will be altered as well.
Is that where the problem is in my function? Because the array is taken as a constant argument and if *largest and *second_largest point to the first element of the array, they essentially cannot be changed either?

As far as writing the function with array notation, I could do that, but I'm just learning about pointers and the book I'm reading required me to write the function with pointer arithmetic and pointer arguments.

The compiler did give the warning: "Assigning to 'int *' from 'const int *' discards qualifiers. Did not know what that means. 5. Originally Posted by Quant89 I thought that [COLOR=#000000][FONT=Consolas][FONT=arial]largest=a and second_largest=a would assign the address of the first element of the array to both pointer variables. Is that incorrect?
That is correct. Originally Posted by Quant89 I learned that array names can be used as a pointer to its first element and both largest and second_largest are pointer variables, so that assignment should be legal.
Yes, array names are converted by the compiler to a pointer to the first element, and the assignment is legal.

Problem is, the assignment is suspicious, for reasons I'll come back to. Originally Posted by Quant89 *largest and *second_largest should then give the values of the first element.
Well, that is true. *largest and *second_largest, given your pointer assignments, are references to the first elements of a. Originally Posted by Quant89 During the loop the elements of the array, *(a+i) that is, are then assigned to *largest depending on whether the conditions hold.
Yes. Except that your understanding is now incorrect.

largest is a pointer to the first element of a (i.e. a). So "*largest = *(a + i)" has the same effect as "a = a[i]". The assignment *largest = <anything> does not change what largest points at. Originally Posted by Quant89 From what I've read about pointers, they simply contain the address of the variable they are pointing to and after assigning a pointer variable to a variable the two are basically "equivalent", in the sense that if I change the value of one of the two, the other will be altered as well.
Yes, but an assignment to *p (where p is a pointer) does not change the value of the pointer p. Your code is misbehaving because you expect "*largest = *(a + i)" to have the same effect as "largest = a + i;". It doesn't. Originally Posted by Quant89 Is that where the problem is in my function? Because the array is taken as a constant argument and if *largest and *second_largest point to the first element of the array, they essentially cannot be changed either?
If you took heed of your compiler warning (see below) you would realise that lines 2 and 4 are suspicious (consistent with what vart told you). "largest = a" causes largest to be a non-const pointer with the same value as the const pointer a. That is suspicious, because subsequently doing "*largest = <something>" is legal, but doing "*a = <something else>" is illegal. Originally Posted by Quant89 The compiler did give the warning: "Assigning to 'int *' from 'const int *' discards qualifiers. Did not know what that means.

"Assigning to 'int *' from 'const int *' discards qualifiers." is compiler-speak for "you have taken a const pointer (a pointer that points at something that CANNOT be changed) and made a non-const pointer (a pointer to something that CAN be changed) from it". 6. Originally Posted by Quant89 largest=a and second_largest=a would assign the address of the first element of the array to both pointer variables.
But you do not want this behavior.

Originally largest and second_largest point to the variables where caller expect to get the result. So you do not want to change where these pointers are pointing, rather cahnge the value of variables they are pointing at.

That's why I would do like this:

Code:
```void find_two_largest( const int *a, int n, int *pLargest, int *pSecond_largest){
int largest = a;
int second_largest = a;
for ( int i = 1; i < n; i++){
...
largest  = ...
second_largest = ...
...
}

//here we have found values we are interested in and stored them into local variables.

//now update the outgoing parameters
if(pLargest)
*pLargest = largest;

if(pSecond_largest)
*pSecond_largest= second_largest;

}``` 7. Thanks a lot for your extensive answer, greatly appreciated. I have some questions left though.

"The assignment *largest = <anything> does not change what largest points at."

Does this only hold because the array was made constant or does *pointer = new value never change what p points to? Basically what I don't understand is whether the address of a variable is changed when its value is changed. If e.g. n is a normal integer variable with the value 10 and p is a pointer variable that points to n, if you then write *p=15, does p point to something else than at the beginning?

"largest = a" causes largest to be a non-const pointer with the same value as the const pointer a. That is suspicious, because subsequently doing "*largest = <something>" is legal, but doing "*a = <something else>" is illegal.

What about an assignment of the form largest = a +i if the condition is satisfied, is that legal? In that case, if the first if condition holds, I could merely change:

Code:
```
temp = *largest;
*largest = *(a + i);
*second_largest = temp;```

to

Code:
```second largest = largest
// second largest now points to formerly largest value
largest = a + i;
// largest now points to the address of the largest element of a up to this point```
unfortunately this still gives me the same error, what did I do wrong here? 8. Originally Posted by vart But you do not want this behavior.

Originally largest and second_largest point to the variables where caller expect to get the result. So you do not want to change where these pointers are pointing, rather cahnge the value of variables they are pointing at.

That's why I would do like this:

Code:
```void find_two_largest( const int *a, int n, int *pLargest, int *pSecond_largest){
int largest = a;
int second_largest = a;
for ( int i = 1; i < n; i++){
...
largest  = ...
second_largest = ...
...
}

//here we have found values we are interested in and stored them into local variables.

//now update the outgoing parameters
if(pLargest)
*pLargest = largest;

if(pSecond_largest)
*pSecond_largest= second_largest;

}```
Thanks for your answer, but if I do it that way, what exactly is the point of using pointers?

Is it not possible to return two values in an int function and using a void function with pointer arguments is the only way to return two or more values? 9. Originally Posted by grumpy snip
Apart from all this, the only errors I can see are lines 2 & 4. 10. Originally Posted by Quant89 Thanks for your answer, but if I do it that way, what exactly is the point of using pointers?

Is it not possible to return two values in an int function and using a void function with pointer arguments is the only way to return two or more values?
I'm not clear what you are asking here.

In regard of returning values from function using pointers as arguments my way does EXACTLY the same what your way should have being doing, if you have not added the bug due to misuse of pointers. 11. Originally Posted by Quant89 "The assignment *largest = <anything> does not change what largest points at."

Does this only hold because the array was made constant or does *pointer = new value never change what p points to? Basically what I don't understand is whether the address of a variable is changed when its value is changed.
It has nothing to do with constness. It has to do with the fact the value of a pointer is an address. The address is where a value (in your case of an int) is stored.

Changing the value of a variable never changes its address. Originally Posted by Quant89 If e.g. n is a normal integer variable with the value 10 and p is a pointer variable that points to n, if you then write *p=15, does p point to something else than at the beginning?
I'm not sure what you mean by "than at the beginning" (they make your question meaningless) so I'll answer your question as if those words aren't there.

The assignment "*p = 15" will change the value of the variable n. It will not change the value of p. It does not change the address of n. The value of p (as distinct from the value of *p) was equal to the address of n before the assignment, and remains equal. Originally Posted by Quant89 "largest = a" causes largest to be a non-const pointer with the same value as the const pointer a. That is suspicious, because subsequently doing "*largest = <something>" is legal, but doing "*a = <something else>" is illegal.

What about an assignment of the form largest = a +i if the condition is satisfied, is that legal?

It is legal but suspicious. If a is a const pointer, a+i is also a const pointer. largest is not so, again, "largest = a + i" discards constness.

And, more significantly, it does not do what you are expecting. Originally Posted by Quant89 In that case, if the first if condition holds, I could merely change: Originally Posted by Quant89 Code:
```
temp = *largest;
*largest = *(a + i);
*second_largest = temp;```

to

Code:
```second largest = largest
// second largest now points to formerly largest value
largest = a + i;
// largest now points to the address of the largest element of a up to this point```
unfortunately this still gives me the same error, what did I do wrong here?
It's a warning actually, although I suggest treating it as an error.

The thing is the address of a variable and the value of a variable are different and distinct things (if they weren't, you could only ever have one variable in your program that has a value 42). You're incorrectly treating them as if they are the same ... sort of. Popular pages Recent additions 