address space of variables changing in c program - c

The address space of an variables seems to be varying in my program. First I got the following output from the program below.
int main(){
int a = 10;
int *b = &a;
int **c = &b;
int ***d = &c;
printf("a - address: %p, value: %x\n",&a ,a );
printf("b - address: %p, value: %x\n",&b ,b );
printf("c - address: %p, value: %x\n",&c ,c );
printf("d - address: %p, value: %x\n",&d ,d );
printf("size: a - %d, b - %d c- %d, d - %d", sizeof(a), sizeof(b), sizeof(c), sizeof(d) );
}
Output:
a - address: 0x7ffc08c5866c, value: a
b - address: 0x7ffc08c58660, value: 8c5866c
c - address: 0x7ffc08c58658, value: 8c58660
d - address: 0x7ffc08c58650, value: 8c58658
which has the difference between the address of a and b as 0xc.
then I add:
int f = 10;
I get this output:
f - address: 0x7fff1945656c, value: a
a - address: 0x7fff19456568, value: a
b - address: 0x7fff19456560, value: 19456568
c - address: 0x7fff19456558, value: 19456560
d - address: 0x7fff19456550, value: 19456558
The difference between the address of a and b changed. Can anyone tell me why?

An int takes 4 bytes and a pointer takes 8 bytes. The pointer also works "best" if its address is a multiple of 8, that is the hex address ends in 8 or 0.
An int likewise has an alignment of 4. So two ints could be stored in the same space as one pointer. When you add f it uses the first 4 bytes and "pushes" a 4 bytes further on. Those bytes were previously unused, so that b could start at an 8-byte boundary.
That still leaves room for the pointer b to start at the same 0-address it used before.

Related

How to double deref in C?

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!".

Same C pointer showing different values?

I'm running this program:
#include<stdio.h>
void main(){
int num = 1025;
int *poinTer = &num;
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 = &num;
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);
}

successive pointer casting in C

I am looking through some example code which employs an API to understand how to properly use the API. I came across some code which I found confusing. Below are the relevant chunks of code:
typedef struct myStruct_id{
randomStruct1 var1;
void *var2;
unsigned char *var3;
randomStruct2 var4;
int var5;
}myStruct_name;
//Function Prototype
void randomFunction(const randomStruct1 *in1, const randomStruct2 *in2, void *handle);
//Global Variables
//assuming data1-5 are of the correct types corresponding to randomStruct1, void, etc.
myStruct_name myStruct_var = {data1, data2, data3, data4, data5};
void *handle = (void*)myStruct_var;
void main(){
myStruct_name *local_var = (myStruct_name *)handle;
//Other code here
local_var.var2 = randomFunction(&local_var.var1, &local_var.var4, &(local_var));
}
My understanding is that the variable handle is a null generic pointer, pointing to the variable myStruct_var (which has been type cast as a null generic pointer). In the main function, the variable local_var is a pointer to the struct myStruct_name, pointing to the value of the pointer handle (which is type cast as a pointer to type myStruct_name) which is pointing to the variable myStruct_var. Next the function randomFunction takes as inputs a pointer just to var1, a pointer to just to var2, and a pointer to the variable local_var.
My confusion is this: the function randomFunction requires as input pointers pointing to structs and a null generic pointer. If local_var is already a pointer, why is the address operator (&) required? Is not the value of local_var already an address? Or is my understanding of what is going on with local_var incorrect?
Also, is there a reason why the final input to randomFunction is parenthetical? That is, why is it &(local_var) instead of just &local_var? Are the parenthesis doing something?
Thanks for reading and any responses!
EDIT: Thanks for the responses indicating I am not referring to a null pointer. I'm referring to the void "data type" here as generic.
If your background is in Java or some other "safe" language, pointers can genuinely be very hard to wrap one's head around. But at the core you're just dealing with memory.
First question - Why address of pointer?
Here's some sample code you can play with. It tries to implement a "shallow" swap in two ways.
#include <stdio.h>
typedef struct {int x; int y; int z;} XYZ;
XYZ s1 = {1, 2, 3};
XYZ s2 = {4, 5, 6};
void swap1(XYZ *a, XYZ *b);
void swap2(XYZ **a, XYZ **b);
int main()
{
XYZ *p = &s1;
XYZ *q = &s2;
printf("Before\n");
printf("Contents s1: %d %d %d s2: %d %d %d\n", s1.x, s1.y, s1.z, s2.x, s2.y, s2.z);
printf("Contents p: %d %d %d q: %d %d %d\n", p->x, p->y, p->z, q->x, q->y, q->z);
printf("Addresses: %p %p %p %p %p %p\n", &s1, &s2, p, q, &p, &q);
swap1(p, q);
printf("Swap 1\n");
printf("Contents s1: %d %d %d s2: %d %d %d\n", s1.x, s1.y, s1.z, s2.x, s2.y, s2.z);
printf("Contents p: %d %d %d q: %d %d %d\n", p->x, p->y, p->z, q->x, q->y, q->z);
printf("Addresses: %p %p %p %p %p %p\n", &s1, &s2, p, q, &p, &q);
swap2(&p, &q);
printf("Swap 2\n");
printf("Contents s1: %d %d %d s2: %d %d %d\n", s1.x, s1.y, s1.z, s2.x, s2.y, s2.z);
printf("Contents p: %d %d %d q: %d %d %d\n", p->x, p->y, p->z, q->x, q->y, q->z);
printf("Addresses: %p %p %p %p %p %p\n", &s1, &s2, p, q, &p, &q);
return 0;
}
void swap1(XYZ *a, XYZ *b)
{
XYZ *t;
t = a;
a = b;
b = t;
}
void swap2(XYZ **a, XYZ **b)
{
XYZ *t;
t = *a;
*a = *b;
*b = t;
}
When you compile and run the above code, you'll get something like this:
Before
Contents s1: 1 2 3 s2: 4 5 6
Contents p: 1 2 3 q: 4 5 6
Addresses: 0x60103c 0x601048 0x60103c 0x601048 0x7ffd29c58288 0x7ffd29c58280
Swap 1
Contents s1: 1 2 3 s2: 4 5 6
Contents p: 1 2 3 q: 4 5 6
Addresses: 0x60103c 0x601048 0x60103c 0x601048 0x7ffd29c58288 0x7ffd29c58280
Swap 2
Contents s1: 1 2 3 s2: 4 5 6
Contents p: 4 5 6 q: 1 2 3
Addresses: 0x60103c 0x601048 0x601048 0x60103c 0x7ffd29c58288 0x7ffd29c58280
Note that swap 1 didn't do anything, it was only at swap 2, where addresses of the pointers were used, that a swap happened. Also note that s1 and s2 were left unaltered. You might use this function to implement a sort which doesn't need to copy entire structures.
Second question: Why &(local_var) vs. &local_var?
The differences are not functionally significant. It might have been a remnant of a previous expression, cut & paste, anything. Lots of reasons.

Not showing the correct value at the address given by pointer

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.

increase gradually the address of a pointer

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 = &num;
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.

Resources