I am a new student in c programming, and I made a small program to see in the action, all the combinations of ++ in the pointers. So I codded: (i run it in Ubuntu via virtualbox)
#include <stdio.h>
main()
{
int num = 1;
int *p = #
printf("\nnum position: %p num value: %d\n", p, num);
*p += 1;
printf("\n---- *p += 1; -----\n");
printf("num position: %p num value: %d\n", p, num);
*p++;
printf("\n---- *p++; -----\n");
printf("num position: %p num value: %d\n", p, num);
(*p)++;
printf("\n---- (*p)++; -----\n");
printf("num position: %p num value: %d\n", p, num);
++(*p);
printf("\n---- ++(*p); -----\n");
printf("num position: %p num value: %d\n", p, num);
++*p;
printf("\n---- ++*p; -----\n");
printf("num position: %p num value: %d\n\n", p, num);
}
Output:
num position: 0xbfce07b8 num value: 1
---- *p += 1; -----
num position: 0xbfce07b8 num value: 2
---- *p++; -----
num position: 0xbfce07bc num value: 2
---- (*p)++; -----
num position: 0xbfce07bd num value: 2
---- ++(*p); -----
num position: 0xbfce08bd num value: 2
---- ++*p; -----
num position: 0xbfce08bd num value: 2
I have understood the different usage of ++. However my question is about the addresses (i just write the 4 digits) At first the address is : 07b8 after the 1st increment the address is 07bc (increased by 4 (HEX) ) after the 2nd increment the address is 07bd (increased by 1 (hex)) after the 3nd increment the address is 08bd (increased by 100 (hex))Why the increment of the address isn't stable?
Your program has undefined behavior: your code cannot write to *p after it has been advanced, because at that point the pointer points to memory not allocated to an int. Because of the way your variables are declared it appears that after the first increment the pointer is actually pointing to itself! Printing the address of the pointer &p should confirm that.
To fix this issue, change your program as follows:
int data[] = {0,0,0,0,0,0,0,0,0,0};
int *p = data;
Now you can increment your pointer up to ten times without the risk of writing to memory outside of the range allocated to your program.
Note: %p expects a void* pointer, so you should insert an explicit cast.
This happens because generally the memory isn't allocate sequentially by the O.S. As a start you can read more here.
Related
I'm a beginner in C language.
I'm practicing several codes on my own, while doing I came across this algo.
Below is the code.
#include <stdio.h>
int main() {
int a = 1;
printf("value of a = %d\n", a);
printf("address of a = %u\n", &a);
int *p;
printf("value of p = %d\n", p);
p = 2;
printf("value of p = %d\n", p);
a = a+p;
printf("value of addition =%d\n", a);
return 0;
}
**OUTPUT**
value of a = 1
address of a = 947268620
value of p = 947268880
value of p = 2
value of addition =6
Why I'm getting 6 instead of 3,
is there anything I'm missing on result
because you're not setting the value of the address p is pointing to to 2, you're assigning/pointing the variable int *p to the value 2 in memory, which is not memory you should be accessing. Instead, you need to point p to memory you have access to (a variable or dynamically allocated memory) and dereference the pointer using *p = 2 which accesses the value that p is pointing to. Your code should instead look like this
int a = 1;
printf("value of a = %d\n", a);
printf("address of a = %u\n", &a);
int _p = 0;
int *p = &_p;
printf("value of p = %d\n", *p);
*p = 2;
printf("value of p = %d\n", *p);
a = a+*p;
printf("value of addition =%d\n", a);
One has to "walk right past" the compiler warnings about that code.
Below is the same code with coercive casting to silence some of the warnings. An additional calculation and print statement should make obvious how the compiler deals differently with the values of pointers (memory addresses) and the values of integers.
#include <stdio.h>
int main() {
int a = 1;
printf("value of a = %d\n", a);
printf("address of a = %u\n", &a); // incorrect format spec for printing address
int *p;
printf("value of p = %d\n", p); // uninitialised and undefined behaviour
p = (int*)2; // coercive casting integer to pointer-to-integer
printf("value of p = %d\n", p); // incorrect format spec for a memory address
a = (int)(a + p); // coercive casting address to integer
printf("value of addition =%d\n", a);
// ADDED these statements
a = 1; // restore value of a
a = a + (int)p; // coercive casting address to integer
printf("value of addition =%d\n", a);
return 0;
}
value of a = 1
address of a = 1703728
value of p = 1
value of p = 2
value of addition =6
value of addition =3 <== was this the expected result?
C will try to do its best with explicit program statements.
"Garbage in, garbage out."
Write correct code, not 'cute' code.
Thanks for your response Awayy. Helpful.
I got the output I needed. But the thing I need to know is, in what logic
the line a = a+p; gave 6 as result in my code.
As u said I'm assigning 2 as address to p(which is p = 0x2).
So, when the addition happens a = 1 and p = 0x2 which has a random value that we don't know that is because I'm not assigning a particular address to the pointer variable p. It results 6 I'm I right.
Trying to double dereference and print them (TOP TWO ARE EXAMPLES):
printf ("a's value = %d \n", a) ;
printf ("a's address = %p \n", &a) ;
printf ("a_ptr_ptr deref'ed defer'ed =d% \n",
What would go after the \n", for a_ptr_ptr deref'ed defer'ed
If you want the address of the address of a, you're going to have to store a's address in a pointer variable, and take the address of that. But having done so, yes, you can double-dereference that pointer with **, and get a's value back. Something like this:
int a = 5;
int *ip = &a;
int **ipp = &ip;
printf("ipp = %p\n", ipp);
printf("*ipp = %p, ip = %p, &a = %p\n", *ipp, ip, &a);
printf("**ipp = %d, *ip = %d\n", **ipp, *ip);
Theoretically you can continue this as long as you like:
int ***ippp = &ipp;
int ****ipppp = &ippp;
int *****ippppp = &ipppp;
printf("*****ippppp = %d\n", *****ippppp);
But by now this is mostly a game; there's no practical use in a real C program for a 5-level pointer, and at some point (after 8 or 10 levels, I think) the compiler's allowed to say "All right, enough, game over!".
I'm running this program:
#include<stdio.h>
void main(){
int num = 1025;
int *poinTer = #
char *pointChar = poinTer+1;
*pointChar = 'A';
printf("Size of Integer: %d\n", sizeof(int));
printf("Address: %d, Value: %d\n", poinTer, *poinTer);
printf("Address: %d, Value: %c\n", poinTer+1, *(poinTer+1));
printf("Address: %d, Value: %c\n", pointChar, *pointChar);
}
*pointChar and *(poinTer+1) should output same result but the output that I'm getting is different. *pointChar is not outputting any value:
Size of Integer: 4
Address: 1704004844, Value: 1025
Address: 1704004848, Value: A
Address: 1704004673, Value:
What's happening here?
When you perform + 1 on a pointer, it does not necessarily increase the memory address by 1. It increases it by sizeof(*ptr).
In this case, poinTer + 1 is equivalent to (char*)poinTer + sizeof(int). This actually makes dealing with arrays much easier.
The good old fashioned ptr[i] is syntactic sugar for *(ptr + i). So, if you have an array of 10 integers, ptr[4] will point to the 5th element rather than 4 bytes away from the base address (since integers are generally 4 or 8 bytes).
So what you've actually done is:
Create an int (num) on the stack and gave it the value 1025
Created a int*(poinTer) on the stack and assigned it the memory address of num
Incremented the pointer by sizeof(int) (which unintentionally points to a different memory address), then cast it to a char* and assigned it to a new pointer.
Assigned the byte pointed to at this new memory address the value 65 ('A').
This is probably what you wanted to do:
#include<stdio.h>
void main(){
int num = 1025;
int *poinTer = #
char *pointChar = (char*)poinTer + 1;
*pointChar = 'A';
printf("Size of Integer: %d\n", sizeof(int));
printf("Address: %d, Value: %d\n", poinTer, *poinTer);
printf("Address: %d, Value: %c\n", (char*)poinTer + 1, *((char*)poinTer+1));
printf("Address: %d, Value: %c\n", pointChar, *pointChar);
}
I am making an error somewhere at the last line. It is not showing the correct value at the address.
/* an array with 5 elements */
double balance[5] = {1000.0, 2.0, 3.4, 17.0, 50.0};
double backup[5];
double *p;
double address;
int i = 0;
memcpy(&backup, &balance, sizeof(balance));
p = backup;
/* output each array element's value */
printf( "Array values using pointer\n");
for ( i = 0; i < 5; i++ )
{
//printf("*(p + %d) : %f\n", i, *(p + i) );
printf("&p[%d] : %f\n", i, p[i]);
printf("&p[%d] : address: %p\n", i, (void*)(&p+i));
}
int offset = 4;
printf("Contents of &p[%d] : address: %x is %f\n", offset, ((&p)+(offset)), p[offset]);
double* newPointer;
newPointer = ((&p)+(offset));
printf("The content again: %f at address: %x\n", *(newPointer), newPointer);
// output is incorrect
The content again: 0.000000 at address: 28feec
Just from the typing I'd say, this:
newPointer = ((&p)+(offset));
should be:
newPointer = p + offset;
This:
((&p)+(offset))
returns a double **, as you take the address of a double *. Adding to this any offset still leaves it a double **. This you surely would not like to assign to a double *.
I am making an error somewhere at the last line
This mistake of taking the address of p is also made at several other location before "the last line".
And to point this out again:
To print out a pointer's value cast it to void * (if it isn't one already) and use the p conversion specifier:
printf("The content again: %f at address: %p\n", *newPointer, (void *) newPointer);
Using x or d or i offers you a fair chance to lose half of the address' significant bits.
memcpy(backup, balance, sizeof(balance));
p = backup;
printf( "Array values using pointer\n");
for ( i = 0; i < 5; i++ ){
//printf("*(p + %d) : %f\n", i, *(p + i) );
printf("p[%d] : %f\n", i, p[i]);
printf("p[%d] : address: %p\n", i, (void*)(p+i));
}
int offset = 4;
printf("Contents of p[%d] : address: %p is %f\n", offset, p+offset, p[offset]);
double* newPointer;
newPointer = p+offset;
printf("The content again: %f at address: %p\n", *newPointer, newPointer);
double *p; Here p itself is a address locating pointer p. So while adding an offset just do, p + offset
Here is an diagrammatic representation how pointer behaves. p is a pointer pointing/holding address of backup. So p has address 0x2000 but &p is address of p which is 0x3000. Therefore &p + offset leads to different memory location which is happening in your case.
p backup
+------+ +------+
| | | |
|0x2000|------------>|0x1000|
| | | |
+------+ +------+
0x3000 0x2000
Also use,
%p format specifier for pointer addresses.
#include<stdio.h>
#include<stdlib.h>
int main ()
{
int a[]={0,1,2,3,4};
int *p[]={a,a+1,a+2,a+3,a+4};
int **ptr=p;
ptr++;
printf("%d %d %d\n",ptr-p,*ptr-a,**ptr);
*ptr++;
printf("%d %d %d\n",ptr-p,*ptr-a,**ptr);
*++ptr;
printf("%d %d %d\n",ptr-p,*ptr-a,**ptr);
++*ptr;
printf("%d %d %d\n",ptr-p,*ptr-a,**ptr);
return 0;
}
The answer for this program is
1 1 1
2 2 2
3 3 3
3 4 4
with gcc.But why is the output for the first printf giving 1 1 1 shouldn't it be 4 4 1?
lets say if p=6004 and and ptr would be 6004 and ptr++ would be 6008.then ptr-p should give 4.pls correct me.thanks..
The result of pointer arithmetic is not exactly the result of their address arithmetic. The output should be ((address of ptr) - (address of p)) / (sizeof(pointed_type))
For example:
int a[] = {0,1,2,3,4};
int *p=a;
int *p2 = p+1;
printf("%d",p2-p) // will print 1
I modified it a little to be certain. The point here is that subtracting pointer returns the number of units i.e. address / size of pointer, not plain difference of address locations.
printf("ptr before %p\n", ptr);
ptr++;
printf("ptr after %p and p %p\n", ptr, p);
printf("%ld %ld %d\n",ptr-p,*ptr-a,**ptr);
On my 64 bit machine, the printed addresses are 8 locations apart with just a single ++. On a 32 bit machine this would be 4. But still the arithmetic difference would return 1.