c - simple pointer query, initializing a pointer - c

I'm kinda confused:
int* p=1000;
printf("%d\n", (int)(p+sizeof(int))); // what is going on here?
does p point to 1000 or does p = the memory address 1000? If it is the former, could this be achieved achieved like this:
int dummyVariable = 1000;
int * p = &dummyVariable;

The declaration
int* p=1000;
makes p point to the address 1000.
While in the case of
int dummyVariable = 1000;
int * p = &dummyVariable;
you initialize dummyVariable to the value 1000 and make p point to dummyVariable.
Another way to look at it:
In the first case you have
Address 1000
|
v
+---+ +-----+
| p | --> | ??? |
+---+ +-----+
And in the second case you have
Address &dummyVariable
|
v
+---+ +----------------------------+
| p | --> | dummyVariable (value 1000) |
+---+ +----------------------------+
A third way of looking at it, is that the value of p is an integer (that just happens to be an address). In the first case p contains the value 1000, i.e. it's pointing to the address 1000.
In the second case the contents of p is &dummyVariable, i.e. it points to the location in memory where dummyVariable is stored.
As for the printout in the first example giving you the value 1016, that's because of how pointer arithmetic works: Whatever you add to a pointer is multiplied by the size of the base type. So if you have a pointer to int, then everything you add to that pointer will be multiplied by sizeof int.
In your case, the size of int is 4 bytes, so what you are doing is actually 1000 + 4 * 4 which is equal to 1016.

In your example, p is storing the memory address 1000, whatever that memory address is holding. In fact, p resides at another memory address, which, again stores the number 1000, which is a memory address, etc. Your second example is correct: The pointer p is assigned the memory address of dummyVariable, now if you modify dummyVariable or the *p (dereferencing the pointer), the changes will be applied to both (because they point to the same memory space).

int* p=1000;
p is a pointer pointing to memory location 1000.
printf("%d\n", (int)(p+sizeof(int)));
You are trying to access some memory here.( 1000 + sizeof(int))
Directly assigning some random address to a pointer as done here is not a good idea.
You should have got below mentioned warnings:
warning: initialization makes pointer from integer without a cast
warning: cast from pointer to integer of different size
The second part:
int dummyVariable = 1000;
int * p = &dummyVariable;
Here 1000 is a value and pointer p is pointing to a memory location holding 1000.
So both are diffrent.

Related

Why is 'a' displayed as 40 in ouput?

int a;
int *p=&a;
a = 20;
*p = 40;
printf("%d",a);
Output:
40
Can anyone explain why the output is 40?
Lets draw it out:
+---+ +---+
| p | --> | a |
+---+ +---+
That is, the variable p points to the variable a.
When you use *p you follow the pointer to get a.
So *p = 40 is equivalent to a = 40.
In this code, the a variable is declared as an int, and it is initialized with the value 20. A pointer p is then declared, and it is initialized with the address of the a variable.
Next, the value of the a variable is modified by using the pointer p. The * operator is used to dereference the pointer, which means that it gives us the value stored at the address that the pointer points to. In this case, the pointer p points to the a variable, so when we dereference p and assign the value 40 to it, we are effectively assigning the value 40 to the a variable.
Since the value of the a variable was previously set to 40 using the pointer, the output of the printf statement is 40.
The output is 40 because the pointer is used to modify the value of the a variable, and the printf statement prints the modified value of a.

can anybody help me to solve this pointer question in c

can anybody help me understand this code (in c)..
#include <stdio.h>
void main()
{
const int a =5;int b;
int *p;
p= (int *) &a;
b=a;
*p= *p +1;
printf(" value of p is = %d\n", *p);
printf(" value of b is = %d\n", b);
printf(" value of a is = %d\n",a);
}
result is
: value of p is = 6
: value of b is = 5
: value of a is = 6
With the instruction p = (int *)&a; you made p to point at a.
As a result expression *p refers to the variable a, hence *p = *p + 1; worked as equivalent to a = a + 1; – variable a got assigned its previous value (which was 5) incremented by 1.
So it's finally 6.
This, however, is an Undefined Behavior, as #interjay points out in this comment – the a variable is declared as const, which means it must not be modified. As a result the compiler might choose to allocate it in a read-only area of memory. It did not in your case, and an assignment succeeded, but in other case the modfication of the variable might silently fail (with a value remaining 5) or yield a memory access exception (and terminate the program) or whatever.
The intent of this code is to update the value of a through the pointer p. Let's strip away some things and start with the basics:
int a = 5;
int *p = &a;
We have an object named a that stores the integer value 5. We have another object named p that stores the address of a. After the two declarations above, the following conditions are true:
p == &a == some address value
*p == a == 5
The expression *p is equivalent to the expression a - assigning a new value to *p is the same as assigning a new value to a, so
*p = *p + 1
is the same as writing
a = a + 1
However, in the code you posted a has been declared as a const int. That means you are telling the compiler that the value of a is not supposed to change over its lifetime. The compiler will flag any statement like
a = a + 1
or
a++;
as an error. The compiler may also store a in read-only memory; if you never take the address of a (that is, if it's never the operand of unary &), the compiler may not reserve any storage for it at all and just replace any instance of it with the value (IOW, anywhere you would expect to see a reference to a in the machine code you would just see a literal 5), meaning there's nothing to write to at all.
But this code cheats - it declares p as a pointer to a non-const int. The type of the expression &a is const int * (pointer to const int), but the type of p is just int * (pointer to int). In the assignment
p = (int *) &a;
you are casting away the const qualifier on a. So when you write a new value to *p, the compiler doesn't know that you're trying to modify something that was declared as const so it won't flag it as an error.
The C language definition says that trying to update a const-qualified object through a non-const-qualified lvalue1 results in undefined behavior - the compiler is not required to handle the situation in any particular way. The result can be any one of:
a runtime error;
the value of a remaining unchanged;
behaving exactly as expected;
or something else entirely.
An lvalue is any expression that designates an object such that the object my be read or modified. Both a and *p are lvalues that refer to an integer object containing the value 5
Before the explanation, let me tell you that this is part is a bit problematic, and can lead to undefined behavior:
const int a =5;
p= (int *) &a;
You should remove const, because in this case you want to modify the contents of a through pointers. Some compilers (such as clang, as someone mentioned in the comments) might perform optimizations, like replacing where the const variable is used with its value, to reduce the number of memory access operations.
Let's imagine that each variable is a little box where you can put numbers. So you have 3 boxes:
+---+ +---+ +---+
| 5 | | | | |
+---+ +---+ +---+
a b p
Now let's go over each statement and see what is happening.
int *p;
p= (int *) &a;
p is defined as a pointer, which is a type of variable that can hold the address of something in memory. In this case, it is assigned the address of variable a. So our boxes now look like this:
+---------------+
v |
+---+ +---+ +----+
| 5 | | | | &a |
+---+ +---+ +----+
a b p
p simply contains the memory address of a. You can print it with printf("%u", a), and you will see some number. That is the address of a.
b=a;
Here we are copying the value of a into b, so our boxes become:
+---------------+
v |
+---+ +---+ +----+
| 5 | | 5 | | &a |
+---+ +---+ +----+
a b p
*p= *p +1;
Using the *p syntax, we can dereference the pointer, that means that we can access the memory that p is pointing to (follow the arrow). In this case, *p will allow us to get or set the contents of the a variable. Our boxes now become like this:
+---------------+
v |
+---+ +---+ +----+
| 6 | | 5 | | &a |
+---+ +---+ +----+
a b p
printf(" value of p is = %d\n", *p);
Here you are again dereferencing p, meaning that we are getting the contents of the memory at address p. In our case, this will get the contents of the a variable which is 6.
printf(" value of b is = %d\n", b);
Looking at the b box, we can see that it contains 5.
printf(" value of a is = %d\n",a);
We modified a using the pointer. Looking at the a box, we can see that it contains the value 6.
We go line by line
const int a =5;int b;
In this line, variable b is defined as int and variable a is defined as const int, which means that its value is constant at all lower steps and is equal to 5.
int *p;
p= (int *) &a;
In these two lines, a variable called p is defined as a pointer int, whose value (must be an address from memory cells) is equal to the address of the variable a.
This means that both variables a and p point to a common memory cell.
In other words:
(*p == a) //IS TRUE. Both are equal to 5
and next line:
b = a;
That is, the value of the variable b is also equal to a, which is equal to 5
*p= *p +1;
In this line, a unit is added to the value corresponding to the address p.
We know that the variables a and p point to a common cell of memory.
In fact, this means that we indirectly added a unit to the variable a, which means that both variables have a value of (5 + 1).
And finally, the reason for the output of the last three lines is clear
The problem is entirely in the following line:
p= (int *) &a;
Without the type cast, the line would read:
p = &a;
The type of a is const int.
The type of p is int *.
It is obvious that the compiler should warn about discarding the const qualifier:
warning: assigning to 'int *' from 'const int *' discards qualifiers
[-Wincompatible-pointer-types-discards-qualifiers]
This demonstrates why you should always try to avoid explicit type casting (unless strictly necessary). The author of this code shot themselves in the foot. They introduced undefined behaviour and the obvious problem was hidden, because the warning was discarded or suppressed

Why p and *p giving the same address when p points to an array?

I was writing this program -
#include<stdio.h>
void main()
{
int arr[20];
arr[0]=22;
arr[1]=23;
int (*p)[20]=&arr;
printf("address in p :%u:\n",p);
printf("address in *p:%u:\n",*p);
}
The Output of this code is same for p and *p ! So far as I know *p is holding the base address of arr which is nothing but arr[0]!!!
So *p should have give the output 22 ! But it's showing the same memory address like p is showing. Please tell me why this is happened? What is the reason behind it.
Codepad Site Link : http://codepad.org/LK7qXaqt
p is a pointer to an array of 20 integers. Address of first byte of array is said to be the address of the array. Dereferencing it will give the entire array itself. Therefore *p represents the array arr, so you can think of *p as an array name.
As array names are converted to pointers to its first element when passed to a function, *p is decayed to pointer to first element of arr. Therefore
printf("address in *p: %p:\n", (void*)*p);
will print the address of first element of array arr while
printf("address in p: %p:\n", (void*)p);
will print the address of the entire array (i.e first byte of the array). Since value of first byte and first element is same, that's why both are printing the same address.
For detailed explanation: What exactly is the array name in c?
Because p and *p points to same memory location only there types are different
+-+-+-+-+-+-+-+-+-+-+-+-+
| | | | | | | | | | | | |
+-+-+-+-+-+-+-+-+-+-+-+-+
arr [ ]
p [ ]
(*p)[ ]
If you print p+1 and *p + 1 you should see the difference
int (*p)[20] declare p as pointer to array of size 20 of type int so at the same time *p is the pointer to the first element of the array.
Address of first element and of whole array would be same.
Yes it is possible to apply the address operator to an array, although it seems redundant. The result p is a pointer to array. Such a thing is under normal circumstances rarely encountered. As #Mohit pointed out correctly, the object it points to is the whole array, which implies that sizeof(*p) should be the size of the array (not of its first element).
*p logically is the array then; as usual it decays to a pointer to its first element (which is an int) when passed as an argument, e.g. to printf. Since it's the first element its location in memory is the location of (the beginning of) the whole array.

Pointer initialisation gives segmentation fault

I wrote a C program as follows:
CASE 1
int *a; /* pointer variable declaration */
int b; /* actual variable declaration */
*a=11;
a=&b;/* store address of b in pointer variable*/
It gives a segmentation fault when running the program.
I changed the code as follows:
CASE 2
int *a; /* pointer variable declaration */
int b; /* actual variable declaration */
a=&b;/* store address of b in pointer variable*/
*a=11;
Now it's working fine.
If anyone knows please explain why it is giving a segmentation fault in CASE 1.
CASE .1
int *a; /* pointer variable declaration */
int b; /* actual variable declaration */
*a=11;//Not valid means you are not owner of the address where a now pointing it is unknown and accessing this will segfault/
a=&b;/* store address of b in pointer variable*/
This is going to be segmentation fault because the address you are using is not a valid address and there you are storing 11 which is illegal.
b
+-------+ +--------+
| + | 11 |
|Unknown| | |
+---+---+ +---+----+
| |
| |
+ +
a a
CASE .2
int *a; /* pointer variable declaration */
int b; /* actual variable declaration */
a=&b;/* store address of b in pointer variable*/
*a=11;
Now its working fine because the address of b is valid an there you are storing 11 which is legal.
Also above cases are not correct way of pointer declaration
int *a = NUll;
a = malloc(sizeof(int));
*a=5;
free(a);//must
or
int *a = NUll;
int b;
a = &b;
*a=5;
This will remove segmentation fault many times which is hard to find .
int *a; // a pointer variable that can hold a memory address of a integer value.
In case 1,
*a = 10; // here you have asigned 10 to unknown memory address;
It shows segmentation fault because of assigning value to a memory address that is not defined. Undefined behaviour.
In case 2,
a=&b; // assigning a proper memory address to a.
*a=11;// assigning value to that address
Consider this example:
#include<stdio.h>
int main()
{
int *a,b=10;
printf("\n%d",b);
a=&b;
*a=100;
printf("-->%d",b);
}
Output: 10-->100
Here this is how it works.
b // name
----------
+ 10 + // value
----------
4000 // address
Asuuming memory location of b is 4000.
a=&b => a=4000;
*a=100 => *(4000)=100 => valueat(4000) => 100
After manipulation it looks like this.
b // name
----------
+ 100 + // value
----------
4000 // address
One line: First code you are dereferencing uninitialized pointer which exhibits undefined behaviour, and in the second code you are dereferencing initialized pointer which will give access to the value at the address.
A bit of explanation:
First you need to realize that a pointer is nothing but an integer, an with the *var we tell the compiler that we will be using the content of the variable var (the integer in it) as an address to fetch the value in that address. If there is **var similarly we tell the compiler that we will first use the stored value of the variable var to fetch the value at the address and again use this fetched value as an address and fetch the value stored in it.
Therefore in your first declaration it is:
+----------+ +----------+
| garbage | | garbage |
+----------+ +----------+
| a | | b |
+----------+ +----------+
| addr1 | | addr2 |
+----------+ +----------+
Then you try to use the value stored in a as an address. a contains garbage, it can be any value, but you do not have access to any address location. Therefore the next moment when you do *a it will use the stored value in a as an address. Because the stored value can be anything, anything can happen.
If you have permission to access the location , the code will continue to execute without a segmentation fault. If the address happens to be an address from the heap book-keeping structure, or other memory area which your code allocated from heap or stack then when you do *a = 10 it will simply wipe off the existing value with 10 in that location. This can lead to undefined behaviour as now you have changed something without the knowledge of the context having the actual authority of the memory. If you don't have permission to the memory, you simply get a segmentation fault. This is called dereferencing of an uninitialized pointer.
Next statement you do a = &b which just assigns the address of b in a. This doesn't help, because the previous line has dereferenced an uninitialized pointer.
Next code you have something like this after the third statement:
+----------+ +----------+
| addr2 |---+ | garbage |
+----------+ | +----------+
| a | +--> | b |
+----------+ +----------+
| addr1 | | addr2 |
+----------+ +----------+
The third statement assigns the address of b into a. Before that a is not dereferenced, therefore the garbage value stored in a before the initialization is never used as an address. Now when you assign a valid address of your knowledge into a, dereferencing a now will give you access to the value pointed to by a.
Extending the answer, you need to keep an eye that, even if you have assigned a valid address to a pointer, you have to make sure at the time of dereferencing the pointer the lifetime of the address pointed to by the pointer has not expired. For example returning local variable.
int foo (void)
{
int a = 50;
return &a; //Address is valid
}//After this `a' is destroyed (lifetime finishes), accessing this address
//results in undefined behaviour
int main (void)
{
int *v = foo ();
*v = 50; //Incorrect, contents of `v' has expired lifetime.
return 0;
}
Same in the case of accessing freed memory location from heap.
int main (void)
{
char *a = malloc (1);
*a = 'A'; //Works fine, because we have allocated memory
free (a); //Freeing allocated memory
*a = 'B'; //Undefined behaviour, we have already freed
//memory, it's not for us now.
return 0;
}
int a stores a random integer value. So saying by saying *a, you might be accessing a memory location that is out of bounds or invalid. So it is a seg fault.
In the first case you have declared a pointer but you have not assigned the address to which it has to point hence the pointer would have contained an address that would have belonged to another process in the system (or it would have contained an junk value which is not an address at all or it would have contained an null which can't be an memory address)hence operating system sends an signal to prevent invalid memory operation and hence an segmentation fault occurs.
In the second case you are assigning the address of the variable which has to be updated to the pointer and storing the value which is the correct way of doing and hence there's no segmentation fault.

What is the the output of the following C programme?

I don't know what the compilar is doing with ++*p;
Can anyone explain me pictorically what is going on inside the memory in this code?
int main()
{
int arr[]={1,2,3,4};
int *p;
p=arr;
++*p;
printf("%d",*p);
}
The answer should be 2
The reason is ++*p is is actually incrementing the first member in the array by 1.
You are incrementing the first element in that array by creating another int pointer p that points to the element. The line
++*p
increments the value of the object pointed to by p - in this case it is the first element in the array.
Making up the actual memory addresses and using "ma" for memory address
at memory address starting at 1000 we have 4 continuous 4-byte (sizeof(int) = 4) slots.
each slot contains the integer value given in the array initializer:
arr
ma1000 ... ma1015
_____________________
| 1| 2| 3| 4|
_____________________
arr gives the starting address of the 4 int slots and how many there are.
p holds the address of an integer and refers to one 8-byte slot in memory (assuming we are on a 64-bit system where pointers are 8 bytes - 64 address bits/8bits-per-byte) at location 2000.
After the statement p = arr, p holds the address 1000
p *p or arr[0]
ma2000 .. ma2007 ma1000 .. ma1003
__________ ________
| 1000| | 1 |
__________ ________
*p gives the value at the memory address pointed to by p. p holds memory address 1000 and memory address 1000 contains 1, thus *p results in 1.
++*p says to increment the value of the int "pointed to" by p. p holds memory address 1000 which holds the value 1. The value at address 1000 then goes from 1 to 2
arr
ma1000 ... ma1015
_____________________
| 2| 2| 3| 4|
_____________________
printf then prints the int value at the address "pointed to" by p, which is 2.
p *p or arr[0]
ma2000 .. ma2007 ma1000 .. ma1003
___________ ___________
| 1000| | 2|
___________ ___________
Let's take this line :
++*p
This will first dereference the p pointer, so access arr[0], then increment it.
if you print arr[0] now, it will be 2.
Then you print *p that is the same as printing arr[0], it equals 2.
Try replacing the first element by 41, your code will print 42.
When you have a pointer int *p, then p means "the memory address p points to and *p means "the contents of the memory address where p points to". ++ means pre-increment, which means increase the value by 1. Since the associativity of unary operators such as * and ++(prefix operators) is right-to-left, and * is closer to p than ++ when traversed right-to-left, * operates before ++. Therefore ++*p means "increment the value pointed to by p", not "increment p then get the value". It is clearer to write ++(*p), but it means the same thing.
The thing to understand is the difference between "increment the pointer", which means point to another value (e.g. ++p) and "increment the value that the pointer points to" (e.g. ++*p).
You can work this out, but that is all the information you need to understand it.
This is a very basic concept in understanding of pointers.
p = arr ;
The above code will make the pointer " p " to point towards what the " arr " is pointing to. " arr " itself is pointing to the 1st element.
*arr = *(arr + 0) = arr[0] = 1
*(arr + 1) = arr[1] = 2
*(arr + 2) = arr[2] = 3
and so on...
So now when you do ++(*arr) that means ++(1) = 2
As p = arr, you can do the remaining replacement and math.

Resources