Integer pointer as parameter of function - c

void inc(int *p) {
p += 1;
}
int main() {
int x = 5;
inc(&x);
printf("x = %d\n", x);
return 0;
}
I've figured that this code doesn't increase the value of x.
It works when I change
void inc(int *p) {
p += 1;
}
to
void inc(int *p) {
*p += 1;
}
Kind of got confused with pointers right now.
Can someone help me?
Thank you in advance!

The difference between the two pieces of code is the difference between increasing the address that the pointer contains and changing the actual value.
The first piece of code: p += 1; increases the address that p is pointing to by one. For instance if x is at address 124, then p was first equal to 124 and is now increased to 125 (in a simple scenario, realistically this would increase by more as p is an integer pointer and thus the increase would be more than 1 byte).
The second piece of code: *p +=1; first dereferences the address in p and adds one to the value currently stored in that address. For instance if x is at address 124 and is of the value 42, then p equals 124, but *p is the deferenced pointer and is equal to 42. You can then assign a new value to *p to make the value at address 124 (i.e. the value of x) equal to 43.
EDIT: As mentioned by #Bathsheba, pointers are passed by value to function calls. This means that if we were to do the following, the original pointer y would remain unchanged, whereas the address p is pointing to does change as mentioned above.
void inc(int *p) {
p += 1;
}
int main() {
int x = 5;
int *y = &x;
inc(y);
return 0;
}
As for your second question on structs. Structs pointers still contain the address of the struct in memory, but the 'arrow notation' you refer to will implicitly do the dereferencing of the fields for you.

Related

Why is the pointer giving me this value?

I was studying for a test with the following question with the given output :
#include <stdio.h>
int main()
{
int i = 10;
int *const p = &i;
foo(&p);
printf("%d\n", *p);
}
void foo(int **p)
{
int j = 11;
*p = &j;
printf("%d\n", **p);
}
Output : 11 11
I understand that the address of *p pointing to int i is passed to the function foo. Here, **p is a pointer pointing to *p, where *p points to int i.
In the function, **p pointer changes and points to int j, and the first printf is called and 11 is printed.
What I don't understand is the output from the 2nd printf function. Why is it printing 11, when it should be 10? I've checked and the value of int i and it did not change, so shouldn't dereferencing *p give 10 and not 11.
Can someone explain to me the logic behind what is happening and why is it happening?
First you asign p the address of i and you input the address of p to the function foo and inside the foo function the the value of p becomes what every the value in j (*p = &j). When the memory address changes in the foo function you are not changing it back.
NOTE: There the variable p is not passed by value, It is passed to the function by reference. So any change you do to the p variable inside the foo function will affect the p variable inside the main function because they have the same memory address
The line:
*p = &j;
makes the original variable
int *const p
point to the address of the local variable
int j
After foo is called, that local variable j has since been deallocated from the stack, but p is still pointing to that same stack location which still has that value of 11. So you are illegally accessing deallocated stack memory but it just happens to remain the value of 11. So it is printed a second time.

What is the difference between int* p and int (*p)[] in the context of arrays.?

Using DevCpp with TDM GCC 4.9.2 on Windows 8. But I don't think the platform matters for this question.
I know that we can use a pointer to point to a single data or an array of data.
I have learned about pointer to arrays but never used it. What advantage does one have over the other?
Sample Code...
#include <stdio.h>
int main()
{
int x[2]={10,20};
int *p1= NULL; //simple pointer
int (*p2)[] = NULL; //pointer to an array, specifically
p1 = x;
p2 = &x; //removing the & gives me a warning of "assignment from incompatible pointer types".
printf("x[1] = %d\n", x[1]);
*(p1+1) = 7;
printf("x[1] = %d\n", x[1]);
(*p2)[1] = 55;
printf("x[1] = %d", x[1]);
return 0;
}
Does p1 or p2 have an advantage over the other?
They are completely different.
int *p; - is the pointer to the int
int (*p)[1]; is a pointer to the array (in this case one element only)
In your trivial example the pointer arithmetic will be the same and generated code will be the same. But they still have different types and you may get warnings when compiled.
The "advantages" you will see when your example will be less trivial:
int (*p)[100];
p++; the pointer will point to the next 100 elements int array.
Pointer to an array means a pointer which accepts address of an array.
let's say array is int arr[5],in which size of int is 4 byte.
p is a pointer to an array that accept the address of an int array.
int arr[5];
int (*p)[5];
p=&arr;//address of an array block
let's say the base address is 1000 .So after increment in p it will lead us to 1020 address,because the size of the array block is 20 bytes.
p points to 1000 address
p++;
//Now p points to 1020 not 1004.
Whereas in case of int *q, q will point to 1004 as usual.

Pointer value as an argument

The value in the printf hasn't changed after applying the void function f, which is confusing me. It's basic stuff revolving pointers. The exact question is: Why isn't the end value 2 instead of 1?
int a=1, b=2;
void f(int* p) {
p=&b;
}
int main() {
int *p=&a;
f(p);
printf("%d\n", *p);
}
The *p value in main remains 1, and that's what's confusing me.
You need to dereference p and remove the & address operator from b
This assigns the value of b to the address where p points to:
void f(int* p)
{
*p = b;
}
The reson why it printed 1 and not e.g. the address of b is that you assigned: p = &b which just assigns the address of b to the local pointer variable p. This means it does not point to a anymore here. But since this was just a local copy it didn't change the value of the p you passed in main().
This makes it a little more obvious:
void f(int* ptr)
{
// assign a value
*ptr = 1337;
}
int main()
{
int local_integer = 666;
// prints "666"
printf("%d\n", local_integer);
f(&local_integer);
// prints "1337"
printf("%d\n", local_integer);
}
In your code you define a pointer to int on the stack. Its value is the same as the pointer in the main() function which happens to point to the Ä…ddress of the variable a. Then you change its value (so the pointer on the stack now points to b) then you just drop that pointer.
void f(int* p) {
p=&b;
}
That is why if you dereference the pointer in main it still points to the address of the int variable a.

If p is a pointer to int where would one use &p

In the following code p is pointer to an int. It is quite clear that p points to the address of i. Through my research i know &p points to the address of pointer p. But i don't get why would you need separate address for that. And also when would you use &p.
int main() {
int i = 3, *p = &i;
printf("%p",&p);
printf("%p",p);
return 0;
}
If p is pointer to int then
int **q = &p;
When you want to use pointer to pointer, then use the address of a single pointer to assign it to pointer to pointer.
Just to make a point that pointer is also a data-type and it stored in the memory location and it holds a valid memory location as its value. The address in which this valid memory location is stored is given by &p
Your printf() also needs to be fixed. %p expects void *
printf("%p",(void *)p);
But i don't get why would you need separate address for that
You don't, but there exists the address of operator so you can take the address of a pointer, which is what
printf("%p\n", &p);
is printing.
And also when would you use &p
There are cases where this might be useful, consider for example that you need to pass a pointer to a function which could be reassigned into the function, you can do something like this
int allocateIntegerArray(int **pointerToPointer, size_t someSize)
{
if (pointerToPointer == NULL)
return 0;
*pointerToPointer = malloc(someSize * sizeof(int));
return (*pointerToPointer != NULL);
}
then you could use this funciton the following way
int *pointer;
if (allocateIntergerArray(&pointer, 10) == 0)
{
fprintf(stderr, "Error, cannot allocate integer array\n");
/* do some extra cleanup or recover from this error, or exit() */
exit(0);
}
The pointers themselves are also variables and as such they need to be sotred somewhere, so the address of a pointer tells you where is the pointer stored, it's value tells you where it is pointing to.
By knowing where it is stored you can do things like the one explained above.
A trivial example:
int nochange(int *c, int *val)
{
c = val; // Changes local pointer c to point to val
// Note that C passes copies of the arguments, not actual references.
}
int do_change(int **c, int *val)
{
*c = val; // Accesses the real pointer c at its real location and makes
// that one point to val
// Even though c is a pointer-to-pointer copy, its value is
// copied too, and the value is the address of the real c
}
int main()
{
int a = 1;
int b = 2;
int *c = &a; // A pointer is also a datatype that resides in memory
printf("%d\n", *c); // Will print 1
nochange(c, &b);
printf("%d\n", *c); // Will print 1
do_change(&c, &b);
printf("%d\n", *c); // Will print 2 because c now points to b
}
I have a similar answer with a bit more detail here about pointer vs pointer-to-pointer: pointer of a pointer in linked list append

Pointers inside function in C

#include<stdio.h>
int q = 10;
void fun(int *p){
*p = 15;
p = &q;
printf("%d ",*p);
}
int main(){
int r = 20;
int *p = &r;
fun(p);
printf("%d", *p);
return 0;
}
I was playing with pointers. Could not understand the output of this.
Output is coming as 10 15.
Once p is pointing to address of q, why on returning to main function it's value changes? Also why it changed to the value '15' which was assigned to it in the function before '10'.
Because p is fun() is not the same p in main(). p , in each function, is local. So changing one doesn't affect other.
In C, all function parameters are passed by value, including pointers.
*p = 15; will set r to 15 as *p is pointing to the memory occupied by r in main() prior to its reassignment to &q;
Your reassignment p = &q; does not change what p points to in the caller main(). To do that, you'd need to doubly indirect the pointer, i.e. change the function prototype to void fun(int **p){, call it using fun(&p);, and reassign using *p = &q;.
Two steps:
First call to fun(), assigning the address of global int q [holding value 10] to p inside the fucntion scope and printing it. The first output ==> 10;
Once the call returns from fun(), it will hold the previous address, [passed from main()] and hence, will print the value held by that address [which is 15, modified inside fun()].

Resources