pointer arithmetic in C while working with array - c

CASE 1:
#include <stdio.h>
int main()
{
int arr[3] = {2,3,4};
char *p;
p = (char*) arr;
printf(" %p - %d\n",&p, *p);
p = p+1;
printf("%p - %d\n",&p, *p);
return 0;
}
output:
0x7ffde540b000 - 2
0x7ffde540b000 - 0
In above code value of pointer 'p' is increased by 1 - but address doesn't changed.
Again I increased the value of p by 4 (i.e p = p+4).
This time I get the following output -
0x7ffe50a2dff0 - 2
0x7ffe50a2dff0 - 3
pointer move to the location arr[1] and prints the correct value.
but address doesn't changed.
CASE 2:
Now rewritten the above code (removed '&' from print statement)
printf(" %p - %d\n", p, *p);
p = p+1;
printf(" %p - %d\n", p, *p);
output -
0x7ffdb20b9d1c - 2
0x7ffdb20b9d1d - 0
address changed by 1.
and similarly it works correctly when I update the code with p = p+4;
Output -
0x7ffef8735d6c - 2
0x7ffef8735d70 - 3
Address increased by 4.
I am not getting why address is not changed, when I am using '&' in print statement (CASE I).
What is difference between '&p' and 'p' in this case.
OS is Kubuntu and compiler GCC.

p is a variable of type char *
as a char * variable p holds values which represent pointers to characters.
&p is the address where this variable p is stored in memory.
When you write p = p + 1 you change the value of the variable p. But the variable p is the same variable, stored at the same memory, so naturally &p doesn't change.

the &-operator in c gives you the adress where the value is stored. so with &p you get the address where p is stored and NOT the adress of the value p points to. whichs is why the adress in your first case did not change.
case 2: you removed the & so you get the value of the adress where p points to which changes once you increase p.
i hope this is clear now :)

The problem is not what you are doing, but how you are printing the data.
int arr[3] = {2,3,4};
char *p = (char *) arr;
printf(" %p - %d\n", p, *p);
p = p+1;
printf("%p - %d\n", p, *p);
If you substitute the apparitions of &p by just p, then you'll get the results you expected. The problem is that & is read as "get the address of", so &p will return the address in which char * p is stored, ¡and that never changes!
int arr[3] = {2,3,4};
int *p = arr;
printf(" %p - %d\n", p, *p);
p = p+1;
printf("%p - %d\n", p, *p);
That's why your second block of code works. And just above these lines you have something which actually makes more sense, in which p is an int *.
I suggest you take a look at C-Sim (disclaimer: it was created by me), and follow the tutorials. C-Sim will draw a status diagram for code such as the one above.
Hope this helps.

Related

Can someone will please explain the output of this program?

In the below example pointer p is a pointer to a variable a.
I have incremented the value of p by 1, which increases the value by 4 because it is int.
But when I try to print the value of *p, some different value is displayed.
I have also attached the output with the program.
Can somebody explain why that value of *p is displayed?
// POINTERS
#include<stdio.h>
int main(){
int a = 3;
int *p = &a;
printf("Value of p %d \n",p);
printf("Value of *p %d \n",*p);
p = p+1;
printf("After changing : value of p %d \n",p);
printf("After changing : value of *p %d \n",*p);
return 0;
}
Output:
Link
[1]: https://i.stack.imgur.com/sTYlq.jpg
Can somebody explain why that value of *p is displayed?
No, no one can explain why the last print of *p gives the value you see.
And tomorrow it may print another value... or not print at all... or your program may crash... or something different may happen...
It's called undefined behavior.
You are trying to read a memory location (i.e. the original p + 1) as if there is an int located at that location. But there isn't... the C standard doesn't define what has to happen when you do that. So anything may happen.
Further notice that you actually have undefined behavior already here:
printf("Value of p %d \n",p);
^^
Wrong for pointers and therefore undefined behavior
To print a pointer you must use %p and cast the pointer to a void pointer. Like:
printf("Value of p %p \n", (void*)p);
^^ ^^^^^^^
Specifier cast to void-pointer
for void-pointer
So a legal version of your program:
int a = 3;
int *p = &a;
printf("Value of p %p \n", (void*)p);
printf("Value of *p %d \n",*p);
p = p+1;
printf("After changing : value of p %p \n", (void*)p);
// printf("After changing : value of *p %d \n",*p); <-- Illegal so commented out
You are accessing memory you do not (necessarily) have access to.
Imagine a (4-bytes long) is here
+-+-+-+-+-+-+-+-+-+-+-+-+
| | | |a|a|a|a| | | | | |
+-+-+-+-+-+-+-+-+-+-+-+-+
^ ^ ^ ^ ^ ^ ^ ^ <== memory you do not have access to
\------ | <== p points here
\------ <== p+1 points here and the pointer is valid
Accessing memory you do not have access to is Undefined Behaviour.

what does *p contain?

As per multiple sources, a pointer p points to a value when it is dereferenced. Thus, we may say that a pointer contains an address as it's value, and when the dereference operator (*) is used, the value at the address is returned.
A pointer may be assigned a value as follows:
int a = 90;
int *p = &a;
if we assign a pointer it's value as follows:
int *p;
*p = 60;
60 is alloted to p and causes undefined behavior upon dereferencing since 60 is not a valid address. (As per the answer to this question).
However, for the following code:
int a = 90;
int *p = &a;
printf ("p is %d \n",*p);
printf ("a is %d \n", a);
printf ("address is %p \n",p);
*p = 100;
printf ("p is %d \n",*p);
printf ("a is %d \n", a);
printf ("address is %p \n",p);
The following output is recieved :
p is 90
a is 90
address is 0028FED8
p is 100
a is 100
address is 0028FED8
ie, the expression *p = 100 changes the value at a, and not the value contained by p.
HOW ??????
*p = &a doesn't even compile. p is a pointer to int. It currently has an undefined value, therefore assigning anything to *p is undefined behaviour and would most likely crash. However, even if p did point to an int, you could only assign an int to *p, &a is a pointer to int, not an int, so this doesn't compile.
In your second example, *p = 60, the value of p is undefined, so you are trying to store 60 to an undefined location in memory. Instant crash. p isn't modified by this, so your explanation is wrong. p is not set to 60. You can't set p to an int. You can only set it to a pointer to int.
Correct:
p = &a;
*p = 60;
the code you wrote at the begining:
int *p;
int a = 90;
*p = &a;
is not valid, The asterisk (*) in line 1 indicate that it is a pointer, it is not the dereference operator as in line 3.
the following code:
int a = 90;
int *p = &a;
is equivalent to:
int a = 90;
int *p;
p = &a;
(p) is a pointer , and now is pointing at address of (a)
*p = 100;
so, you just assign a value to a, a = 100 .
and you are printing the same value from the same address.
You had asked:
ie, the expression *p = 100 changes the value at a, and not the value contained by p.
You can read the comment section for explanation of each line of C code and I'm not using exact address locations but using arbitrary ones for demonstration purposes:
int *p; // Stack variable pointer to integer type w/ p's address being 4 bytes # 0x00000000
int a = 90; // Stack integer variable `a` and initializing it to the value of 90 located # 0x00000040
*p = &a; // Dereferencing the pointer `p` to be equal to the address of `a` ... One would think
// that the address value of `a` 0x00000040 in hex would be stored into `a` which
// has the value of 64 in decimal, however this is not always the case and this should be
// undefined behavior, but can still compile and run depending on the compiler and architecture.
// It may run or crash or not even compile or build at all. Most compilers should throw an error.
*p = 100; // 'p' is located at 0x00000000 and contains the value 0x00000040 and by dereferencing it
// it will assign the value of 100 to the stack address location of 0x00000040. Thus this
// changes the value of `a` to 100
// These two statements are in a sense equivalent
*p = 100; a = 100;
// If one was to assign the address of `a` to `p` as such:
p = &a;
EDIT
// Therefor the statement `*p=100` will only work if the statement
// `p=&a` is defined and evaluated beforehand.
EDIT
Now as for the question based on the Title: "what does *p contain?" with the op's original code provided *p actually contains garbage or what ever was assigned to it upon declaration.
As per multiple sources, a pointer p points to a value when it is dereferenced.
Not quite. A pointer points to an object. Dereferecing a pointer produces that object. Using an object in a context where a value is needed produces the stored value.
int *p = &a;
The object that p now points to is a.
*p = 100;
Dereferencing p produces the pointed-to object, namely a. Since this is not a context where the stored value is needed, a's value isn't read, it remains the object a which is assigned the value 100.
Or, simply put, *p means a, therefore *p = 100 means a = 100.

C pointer always contains its own memory address?

Why does the pointer p always point to its own memory address as an integer in the following example. I can't see where it is initialized and would guess that it would be a garbage value. Can someone show me why it is not a garbage value. By the way I am compiling this in gcc with -std set to c99.
#include <stdio.h>
int main() {
int *p; int a = 4;
p = &a;
*p++;
printf("%d %u\n", *p, p);
}
Your problem (as the other answers point out) is with *p++;. What that says to do is dereference p then increment the address in p.
From what you are seeing, we can assume p comes directly after a in memory
_________________________________________
|something | a | p | something else |
-----------------------------------------
So what ends up happening is p points to a, then is incremented so it points to itself (or more specifically: p stores the address that p is at).
First you need to print a pointer value with %p, and your code has undefined behavior. You move the pointer one place after a and dereference it.
Your code doesn't illustrate the point you (it seems) wanted, the following will:
#include <stdio.h>
int main() {
int *p; int a = 4;
p = &a;
printf("%d %p %p\n", *p, p, &p);
}
It produces something like:
4 0x7fff5c17da44 0x7fff5c17da48
p points to a then *p is the value of a. The value of p is 0x7fff5c17da44 which is the adresse of a and the address of p (&p) is 0x7fff5c17da48.

Behavior of call by reference

In my program, I am a passing a pointer to a function. In that function, I am making the passed pointer to point to a location what another pointer points. When returned from function it no longer points to its new location, instead it points to its original location. As I am passing by call by reference, it should point to its new location. Why is this happening?
// a program to show behavior of call by reference
#include <stdio.h>
#include <stdlib.h>
void ptrAllocation(int *p)
{
int k = 10 ;
int *t = &k;
p = t ;
printf("\np now points : %d",*p);
}
int main()
{
int i = 5 ;
int *a = &i;
ptrAllocation(a);
printf("\na now points : %d",*a);
}
Output:
p now points : 10
a now points : 5
I know the problem can be solved if I make a function like:
void ptrAllocation(int **p)
{
int k = 10 ;
int *t = &k;
*p = t ;
printf("\np now points : %d",**p);
}
But I am not getting the clear picture of what is happening exactly in the program from the point of view of pointers, location, stack?
MY PROBLEM:
Is that the pointer k points to whatever pointer t points in the function ptrAllocation, but as the function returns, there no longer exists pointer t, hence pointer p points to its original location.
Is it not the case that when assigning a pointer to a pointer like in p = t, both pointers p and k point to the same location and not that p points to t and t points to the location.
Please describe how the stack and the pointers work in the program above.
You are passing by value, not by reference. What you pass by value is a pointer, but the pointer is still passed by value. You can change what it points at; you can't change the pointer in the calling function. If you wanted to do that, you'd have to pass a pointer to the pointer, as in your second code fragment.
Here's a derivative program based on your code, and its output from a 64-bit build on Mac OS X 10.8.3. I used 12 in the address printing to give uniform width pointer output on this machine; you can tune it to suit your machine.
#include <inttypes.h>
#include <stdio.h>
#include <stdlib.h>
static int q = 42;
static void ptrAllocation(int *p, int **z)
{
printf("p now points at: %2d (0x%.12" PRIXPTR ")\n", *p, (uintptr_t)p);
printf("z now points at: %2d (0x%.12" PRIXPTR ") (0x%.12" PRIXPTR ")\n", **z, (uintptr_t)*z, (uintptr_t)z);
int k = 10;
int *t = &k;
*z = &q;
p = t;
printf("After:\n");
printf("p now points at: %2d (0x%.12" PRIXPTR ")\n", *p, (uintptr_t)p);
printf("z now points at: %2d (0x%.12" PRIXPTR ") (0x%.12" PRIXPTR ")\n", **z, (uintptr_t)*z, (uintptr_t)z);
}
int main(void)
{
int i = 5;
int j = 7;
int *a = &i;
int *b = &j;
printf("Before:\n");
printf("a now points at: %2d (0x%.12" PRIXPTR ")\n", *a, (uintptr_t)a);
printf("b now points at: %2d (0x%.12" PRIXPTR ")\n", *b, (uintptr_t)b);
ptrAllocation(a, &b);
printf("a now points at: %2d (0x%.12" PRIXPTR ")\n", *a, (uintptr_t)a);
printf("b now points at: %2d (0x%.12" PRIXPTR ")\n", *b, (uintptr_t)b);
}
Sample output:
Before:
a now points at: 5 (0x7FFF59E1852C)
b now points at: 7 (0x7FFF59E18530)
p now points at: 5 (0x7FFF59E1852C)
z now points at: 7 (0x7FFF59E18530) (0x7FFF59E18538)
After:
p now points at: 10 (0x7FFF59E18534)
z now points at: 42 (0x000105DE8050) (0x7FFF59E18538)
a now points at: 5 (0x7FFF59E1852C)
b now points at: 42 (0x000105DE8050)
Studying the output should help you understand better what is going on. You can print more address values if you need to.
Please describe how the stack and pointers work in the program above.
I'll discuss the program I showed because the addresses are available for discussion.
The variable q is located at address 0x000105DEE8050. Inside main(), variable i is stored on the stack at memory location 0x7FFF59E1852C; the variable j is stored at memory location 0x7FFF59E18530. The variable a contains the address of i; b contains the address of j; the address of b itself is 0x7FFF59E18538; the address of a is not shown in the output.
When ptrAllocation() is called, the value of a is pushed onto the stack, and the address of b is also pushed onto the stack. It is an implementation detail which order the values are pushed.
Inside ptrAllocation(), the variable p contains a copy of the value in a in the main() function. The variable z contains the address of b in the main() function. The variable k is on the stack; the variable t contains the address of k.
The assignment *z = &q; assigns the address of q to the pointer b via the argument z; it changes what b points at by changing the value of b in the calling function — which is only possible because the address of b was passed.
The assignment p = t; changes the local variable p (which contains a copy of what is in the variable a in main()) so that it points to what t points at, which is k. Therefore, the 'After' print statements note that p points at the value 10. The value that **z points at is in q and is still 42; *z is the address of q.
On return, a in the main() code is unchanged because its address was not passed to ptrAllocation(), but b is changed because its address was passed to ptrAllocation() and ptrAllocation() modified the pointer.
As noted in the comments to the question, your second implementation of ptrAllocation() is flawed too:
void ptrAllocation(int **p)
{
int k = 10 ;
int *t = &k;
*p = t ;
printf("\np now points : %d",**p);
}
After calling this function, the pointer passed to it cannot reliably be dereferenced because *p points to a local variable which ceases to be valid once ptrAllocation() returns. You could fix this issue by making k into static int k = 10;, or by arranging for *p to point to some other int value that has a scope outside the function — a variable defined outside the function, or a dynamically allocated variable:
void ptrAllocation(int **p)
{
static int k = 10;
int *t = &k;
*p = t ;
printf("p now points : %d\n", **p);
}
Or:
void ptrAllocation(int **p)
{
*p = malloc(sizeof(*t));
if (*p != 0)
{
**p = 10;
printf("p now points : %d\n", **p);
}
}
Note, incidentally, how the code I've left has the newlines at the end of each printf() statement. Get into the habit of placing newlines at the end of lines of output. If you don't, you don't know when the output will appear (because it may be held up until the next time a newline is generated).
You are changing the pointer in function and not in the main code. Therefore only the copy will be changed. In the later case you change the location of pointer so the value at that address is changed. Take it like variables, when you change the copy, nothing happens to the original but when you change the location, the variable is changed. So you have to pass the address of pointer to change it.
The C language only implements call by value. Call by reference refers to passing (by value) a pointer p, and then using *p to manipulate what it points at (references).
If you want a function to change a pointer, you have to reference the pointer, such as by forming a pointer to pointer, and pass the reference to the function using call by value. The terms "reference" and "pointer" may be used nearly interchangeably in C — referencing is just what a pointer does.
In C++ call by reference is a language feature, but in C it's an idiom.

C question with pointers

I have a program question, here is the code.
int main()
{
int *p,*q;
p=(int*)1000;
printf("%d ",p);
q=(int*)2000;
printf("%d",q);
printf("%d",(p-q));
return 0;
}
But answer coming as
1000
2000
-250
I am unable to understand what happen with p-q and why answer came as -250?
Correct but probably useless answer: p - q is equal to (1000 - 2000) / (sizeof int). For most C compiles, sizeof int is 4.
Potentially more useful answer: the effect of typecasts like (int*) 1000 is undefined. That code creates a pointer to an int at address 1000. That address is probably invalid. To create a pointer to an int with value 1000, write this:
int i = 1000;
int *p = &i;
Now p points to i, and *p, the value pointed to by p, is 1000.
Here is some correct code that may say what you meant:
int main() {
int i = 1000;
int j = 2000;
int *p = &i;
int *q = &j;
printf("i = %d *p = %d\n", i, *p);
printf("j = %d *q = %d\n", j, *q);
printf("*p - *q = %d\n", *p - *q);
}
When you subtract two pointers, as long as they point into the same array, the result is the number of elements separating them.
On your platform, an int is 4 bytes. There are -250 elements between address 2000 and address 1000.
Since p and q don't both point to the same array, the result is undefined. You could get any result, including the one you expect.
So much undefined behaviour in this program, the values printed are really quite immaterial.
p is a pointer variable, which can store only address of a int variable. But you are storing 1000 as an address, which is invalid. And then you are storing 2000 to the variable q.
Now you are doing pointer arithmatic p-q. Always pointer arithmatic will gives the output based on the size of the type of address. Which will work like (p - q)/sizeof(type).
Consider if p and q are char * variable, then p-q will gives you the output as -1000
In your case p and q are int * variable, then p-q will gives you the output as 250 if size of int is 4 bytes. Execute this on the compiler where size of int is 2 bytes, you will get a result as -500.

Resources