An observation about variable memory addresses in C - c

I have a question rather than a problem (witch maybe arises a memory question).. I've written this simple program:
#include <stdio.h>
#include <stdlib.h>
int multi(int x, int y);
int main(){
int x;
int y;
printf("Enter the first number x: \n");
scanf("%d",&x);
printf("Enter the second number y: \n");
scanf("%d",&y);
int z=multi(x,y);
printf("The Result of the multiplication is : %d\n",z,"\n");
printf("The Memory adresse of x is : %d\n",&x);
printf("The Memory adresse of y is : %d\n",&y);
printf("The Memory adresse of z is : %d\n",&z);
getchar();
return 0;
}
int multi(int x,int y){
int c=x*y;
printf("The Memory adresse of c is : %d\n",&c);
return c;
}
As you can see (if you develop in C), this program inputs 2 int variables, then multiplies them with the multi function:
after getting the result , it displays the location of each variable in the memory (c,x,y and z).
I've tested this simple example those are the results (in my case):
The Memory adresse of c is : 2293556
The Result of the multiplication is : 12
The Memory adresse of x is : 2293620
The Memory adresse of y is : 2293616
The Memory adresse of z is : 2293612
as you can see , the three variables x,y,z that are declared in the main function have closed memory adresses (22936xx) , the variable c that's declared in the multi function has a different adress (22935xx).
looking at the x,y and z variables, we can see that there's a difference of 4 bytes between each two variables (i.e : &x-&y=4, &y-&z=4).
my question is , why does the difference between every two variable equals 4?

x, y, and z, are integer variables that will be created on the call stack (but see below). The sizeof int is 4 bytes, so that is how much space a compiler will allocate on the stack for those variables. These variables are adjacent to one another, so they are 4 bytes apart.
You can read about how memory is allocated for local variables by looking for information on calling conventions.
In some cases (where you do not use the address-of operator), the compiler may optimize local variables into registers.

In your situation the three variables were allocated in contiguous memory blocks. On x86 systems, int types are 32-bits wide, i.e. sizeof(int) == 4. So each variable is placed 4 bytes apart from the last.

The size of a machine word on your machine is 4 bytes so, for speed of access by your program they offset each variable on a 4 byte boundary.

Local variables are allocated on the "stack". Often the compiler will put them in sequential order since there's really no reason not to. An integer in C is 4 bytes. Therefore, it makes sense that y comes in 4 bytes after x, and z comes in 4 bytes after y.

It appears that you are running on a 32-bit machine. The size of each int is 32 bits, and with 8 bits in a byte, the size of an int is 4 bytes. Each memory address corresponds to one byte, so there is a difference of 4 between the address of each local variable.

Related

Why are Pointers in Swap Function not Changing values in C?

I'm trying to swap two floats using pointers ,
My code :
#include <stdio.h>
void swap(float* p, float* q);
int main() {
double num1,num2;
printf("Please write 2 numbers ");
scanf("%lf %lf",&num1 , &num2);
swap(&num1,&num2);
printf("\nnum1 is : %.2lf \n",num1);
printf("num2 is : %.2lf \n",num2);
return 0;
}
void swap(float* p, float* q){
float a;
a=*p;
*p=*q;
*q=a;
}
My issues :
The code doesn't swap
The pointers in the swap function show value 0 for the pointer of the address I'm sending .
For example - input 99 22 -> gives me 0 :
Using Debugger I get
I don't get why I'm getting that , if according to this comment I have an address
that I sent (let's assume I sent 00001 ) then a pointer to that address would be my value (99 in this example ) but I get 0 ...
I'd appreciate any help !
As pointed out by comments, the problem is that your swap function takes float pointers while you are using double variables.
Since float type is used to describe floating point value over 4 bytes (32 bits) and the double type describes floating point value over 8 bytes (64 bits), when you pass double pointers to a function that treat them as float type, the values are wrongly assigned (over 4 bytes instead of 8 bytes) from one memory area to another.
The half of bits of a double does not make a valid corresponding float.

negative index in array of pointers in C

#include<stdio.h>
int main(){
int a1[]={6,7,8,18,34,67};
int a2[]={23,56,28,24};
int a3[]={-12,27,-31};
int *y[]={a1,a2,a3};
int **a= y;
printf("%d\n",a[0][2]);
printf("%d\n",*a[2]);
printf("%d\n",*(++a[0]));
printf("%d\n",*(++a)[0]);
printf("%d\n",a[-1][1]);
return 0;
}
When I run the above code output is 8,-12,7,23,8. But if i change the last 3 lines to
printf("%d\n",*(++a[2]));
printf("%d\n",*(++a)[1]);
printf("%d\n",a[-1][1]);
output is 8,-12,27,27,7. I'm unable to understand last printf statement. How does a[-1][something] is calculated ? And according to me *(++a)[1] should print 56 instead of 27 !
Pointers and array bases are in fact addresses in virtual memory. In C, they can be calculated into new addresses. Since the compiler knows the size of memory the pointer points to (e.g. int * points to 4 Bytes), a pointer +/- 1 means the address +/- the size (e.g. 4 Bytes for int).
The operator * means to get the value stored in the specified address.
Another trick here is the priorities of the operators. [] is calculated before ++.
If you understand what I mean above, your problem should be resolved.
according to me *(++a)[1] should print 56 instead of 27 !
++a increments a to the next int *, so after it pointed to y[0] equal to a1, it points to y[1] equal to a2. Then [1] in turn designates the next int * after y[1], i. e. y[2] equal to a3+1 (due to the preceding ++a[2]). Lastly, * designates the int which y[2] points to, i. e. a3[1] equal to 27.

Calculating the address: pointer + non-negative number

Pointers can only move in discrete steps.
int *p;
p = malloc(sizeof(int)*8);
Therefore, formally *(p+2) is calculated as *(p+2*sizeof(int)).
However If I actually code the above two, I get different results, which seems understandable.
*p = 123;
*(p+2) = 456;
printf("%d\n",*(p+2*(sizeof(int)))); \\0
printf("%d\n",*(p+2)); \\456
The question is, is this calculation implicit, done by the compiler at compile time?
The question is, is this calculation implicit, done by the compiler at
compile time?
Yes this is implicit, when you write ptr+n it actually advances forward n times as many bytes as size of pointee type (e.g. in case of int* - this is 4 bytes granted integer takes four bytes on your computer).
e.g.
int *x = malloc(4 * sizeof(int)); // say x points at 0x1000
x++; // x now points at 0x1004 if size of int is 4
You can read more on pointer arithmetic.
Therefore, formally *(p+2) is calculated as *(p+2*sizeof(int)).
No, *(p+2) is calculated as *(int*)((char*)p+2*sizeof(int)).
Even a brief look reveals that the only way for your statement to hold is if sizeof(int) == 1.

what does this code line do?

Hi I am new to C programming can anyone please tell me what this line of code would do:
i = (sizeof (X) / sizeof (int))
The code actually works with a case statement when it takes a value of bdata and compares it to different cases.
Generally, such a statement is used to calculate the number of elements in an array.
Let's consider an integer array as below:
int a[4];
Now, when sizeof(a) is done it will return 4*4 = 16 as the size. 4 elements and each element is of 4 bytes.
So, when you do sizeof(a) / sizeof(int), you will get 4 which is the length or size of the array.
It computes the number of elements of the array of int named X.
returns the length of the array X
it computes X's volume in memory divided by the size of an integer in your computer(2 bytes or 4 bytes). If i is integer than it is an integer division. If it is float and X has no even volume, it is real division.
int size can change. X depends on implementation. Division result depends on type of i.
All these means, it computes how many ints fit into X.
Besides common practice or personal experience there is no reason to think that this i = (sizeof (X) / sizeof (int)) computes the size of the array X. Most often probably this is the case but in theory X could be of any type, so the given expression would compute the ratio of the sizes of your var X and an int (how much more memory, in bytes, does your X var occupy with respect to an int)
Moreover, if X was a pointer to an array (float* X, the alternate way of declaring arrays in C) this expression would evaluate to 1 on a 32-bit architecture. The pointer would be 4 bytes and the int also 4 bytes => i = sizeof(X) / sizeof(int) (=1)

Pointers and Addresses in C

The following code manipulates pointers to point at the same location; I'm puzzled about why when I ran the code, the output didn't show value coinciding.
#include "stdio.h"
main()
{
int i=3,*x;
float j=1.5,*y;
char k='c',*z;
x=&i;
y=&j;
z=&k;
printf("\nAddress of x= %u",x);
printf("\nAddress of y= %u",y);
printf("\nAddress of z= %u",z);
x++;
y++;y++;y++;y++;
z++;
printf("\nNew Address of x= %u",x);
printf("\nNew Address of y= %u",y);
printf("\nNew Address of z= %u",z);
printf("\nNew Value of i= %d",i);
printf("\nNew Value of j= %f",j);
printf("\nNew Value of k= %c\n",k);
}
Output:
Address of x= 3219901868
Address of y= 3219901860
Address of z= 3219901875
New Address of x= 3219901872
New Address of y= 3219901876
New Address of z= 3219901876
New Value of i= 3
New Value of j= 1.500000
New Value of k= c
The new address of variable y and z are same. How can two variables have same address and et have different values?
Note: I used gcc compiler on Ubuntu 9.04
What you are printing is not the address of x/y/z, but rather the address they are pointing at. Then, by modifying the pointers (using ++) you eventually get y and z to point at the same address in memory.
Regarding the values - first thing you should notice that you don't actually change the values of j and k, and by the time you print those values the pointers no longer point to them.
Second thing is, even if you did print the value that the pointers point to, you would still get a different value since in one case the data would be interpreted as a float and in the other as a char.
Ah. The dangers of pointer arithmatic.
So y = &j sets pointer y to tha current address of float "j"
then you say y++ as you have defined y as a float pointer this is interpreted as add the length of a float variable to pointer y.
However you have only defined one floating point "j" so y is now pointing at whatever has been allocated after "j" -- in this case it happens to be the address of the "k" variable which was defined immediatly after -- but in practice it could be anything or nothing.
Had you defined "j" as an array of floating points it would have pointed to the second entry in the array equivalent to j[1]. Incendently C will also allow you to use j[1] even though you have not defined j as an array!
Incrementing pointers this way is only useful if your pointer points to an element in an array.
In fact, incrementing a pointer just increases its value by the size indicated by the type of the pointer, so:
incrementing a char-pointer will add 1 to the address
incrementing a long-pointer will add 4 to the address (on systems where a long is 4 bytes)
and so on
Also, while it is not the case in your examples, two variables may (appear to) have the same address but different values.
Assuming that you did:
void display_addr_and_val(const int& var){
printf("Addr:%p Val:%d\n",&var, var);
}
void main(){
int x=0;
int y=1;
display_addr_and_val(x);
display_addr_and_val(y);
}
.. you could theoretically end up with the same address shown for both x and y (if you turn on optimization) . Because the parameter of "display_addr_and_val" is a const reference, the code can be rewritten as:
void display_addr_and_val(const int& var){
printf("Addr:%p Val:%d\n",&var, var);
}
void main(){
int x=0;
display_addr_and_val(x);
int y=1;
display_addr_and_val(y);
}
now, in this version of the code, you may see that there is no overlap in the lifetime of "x" and "y". Which means that in fact the compiler may choose to use the same stack slot for both of them.
Granted, this doesn't happen very often, but there's not theoretical reason why it shouldn't happen - so the bottom line is that you should use extreme caution when you assume anything about the address of variables - especially local ones (e.g. don't assume that their addresses will be allocated in a given order, or that all distinct variables will use distinct addresses)
It's simple pointer math.
the address of the float is incremented at least by sizeof(float), (it should be 4 but you have an increment of 16, it depends on the hardware and the real size used to store floats) while the address of char is incremented by sizeof(char) (1)
you have that y + 16 = z + 1 which is not surprising, remembering that "the next float" (the "things" y now points to) is not indeed a float, but the memory location after the float and so it is for z (it'll point not to a char);
it just means that the float location is 15 bytes "before" the char location. I.e. y + 15 = z.
EDIT: with y I always mean the address of the float taken with &, and so for z...: i.e. before you incrmented them. y+16 is the incremented value of y (after you did y++) and z+1 the incremented value of z after z++.
EDIT 2: dumb me, I did not note that you increment y 4 times! so sizeof(float) is 4, 4*4= 16 ... ! and it is 4 on your machine too (as expected by IEEE for single precision fp numbers...) and so it means that y + (sizeof(float)*4 = z + sizeof(char) ... it still means y location is 15 bytes before z (the address of the char)

Resources