Difference between returning address and returning pointer - c

#include <stdio.h>
#include <conio.h>
void main()
{
int m = 20;
int n = 30;
int *x = (int *)m;
int *y = (int *)n;
printf("%d", y-x); //Output is 5
}
How is the output 5? One of the reason could be that x and y consider 20 and 30 as address and during pointer arithmetic the value could be (30-20)/(size of int) which is 10/2 = 5.
My doubt is what is the difference between returning pointer and returning address ? Why the address of m was not stored in pointer variable x?

The behaviour of your program is undefined.
Pointer arithmetic - including the difference between two pointers - is only valid within arrays (including one past the end of the arrray), or between the address of a scalar and one past that.
The behaviour of your casts from an int to a pointer to an int is also undefined.
If you do have a valid difference between two pointers, then use the format specifier %td to output it.

The address of m wasn't stored in x because you didn't assign it the address of m. You assigned it the value of m. The cast you applied masked the fact that you attempted to assign an integer to a pointer, which the compiler would have warned you about.
If you want to use the address of a variable, use the address-of operator &:
int *x=&m;
int *y=&n;
You are correct regarding why the output is 5. The values of m and n are assigned to pointers and are thus treated as addresses.
Note however that pointer subtraction is undefined unless both operands point to members of the same array (or one past the end of that array). Also note that it is undefined behavior to print pointers with the %d format specifier. You need to use %p instead, and you need to cast the given parameter to void * (one of the rare cases where a cast to/from void * is required).

if you want to store the adress of m in x simply do int* x = &m;
the casting to int type pointer here is causing the problem in my optinion.
also if you want to calculate the values of y-x then do *y-*x. as it is in your code you calculate the adress of n - the adress of m.

You have to use %p if you would like to show the address that is stored in a pointer. In your code, you should use * before the name of the pointer.
#include<stdio.h>
int main()
{
int m=20; int n=30;
int *x= &m;
int *y= &n;
printf("\n%d", (*y)-(*x)); //Output is 10
printf("\n%p address of m", x);
printf("\n%p address of n", y);
return 0;
}

int *x=(int *)m;
int *y=(int *)n;
By doing this what you would be doing is -
in a pointer x - you put the value m ( Treat this as a pointer as well as you are doing int *.
Hence x would have a value of 20 ( 0x14 ) and y would have a value of 30 ( 0x1E).
Pointer arithmetic is bit different from normal arithmetic operation
https://www.tutorialspoint.com/cprogramming/c_pointer_arithmetic.htm
And about assigning address you should use a &variable to do that

Related

Is "int *x" a pointer to the type int or is it a pointer to an integer value?

In int *x x is a pointer to integer.
If we initialize with a statement something like this: int *x = &p now x is pointing to the address of "p".
The value that it produces is: 6422036
Does that mean in int *x x is a pointer to the type int or it's a pointer to an integer value?
Is it conceptually something like int *x = &int as default?
When I compile this:
#include <stdio.h>
main ()
{
int *x;
printf("%d", x);
return 0;
}
It gives the value 16.
What does it mean?
I think your question is based on a misunderstanding, so I am going to do some bean-counting on your phrasings. (Not contradicting ikegami by the way, just trying to provide a different approach or viewpoint.)
In int *x x is a pointer to integer.
Yes.
if we initialize the statement with something like this: int *x = &p now x is pointing to the address of p.
Not exactly, now x contains the address of p (which hopefully is an int). It is considered to point to p.
The value that it produces is: 6422036
If you say so, but that is not reproducable and you should probably never think or know about that value. Any other value at this point would means the same - or nothing.
Does that mean in int *x x is a pointer to the type int or it's a pointer to an integer value?
Yes.
To be precise, for a C programmer those are one and the same thing.
Whatever it is pointing to is an integer value, i.e. it is of int type. (Skipping the differences of unsigned int, long int, short etc., I am convinced you are not asking about that.)
If you see a difference between those two, then your understanding is not C (I suspect it comes from a different language, see introspection as discussed by ikegami.)
is it conceptually something like int *x = &int as default?
No. There is no such thing as &int in C. It is more like
int *x; /* Don't you dare dereference this before you assigned a decent address.
and be sure to assign an address of something you are actually allowed
to at least read - or expect little demons flying out of your nose. */
Note that "demons flying out of your nose" is practically a technical term used among programmers to describe that absolutely anything can happen, usually undesired things. Most undesired possible result is that it passes all tests and then fails catastrophically in the most inconvenient situation.
Actually it is called undefined behaviour.
C doesn't have reflection. There's no int type in memory, just values of that type. As such, x isn't a pointer to the type int. It is indeed a pointer to an integer value.
Given int *x, we can say:
*x is an int
x is an int*, which is to a pointer to an int.
That assumes x has been properly initialized and isn't NULL. This isn't the case in your program. Reading x before giving it a value is a bug.
Also, providing a pointer to %d is a bug. To display a pointer, you need
printf("%p\n", (void*)x); // One of the weird times when a `void*` cast is needed.
Again, this is only legit after you initialize x.
A valid program:
#include <stdio.h>
int main(void)
{
int i = 123;
int *p = &i;
printf("%p\n", (void*)p);
printf("%p\n", (void*)&i);
printf("%p\n", (void*)&p);
printf("%d\n", i);
printf("%d\n", *p);
return 0;
}
Does that mean in int *x x is a pointer to the type int or it's a pointer to an integer value?
x is an object stores values of type int *; that is, it stores the address of an int object.
It gives the value 16.
What does it mean?
It means you've invoked undefined behavior - you're using the wrong format specifier for the type.
The proper way to print a pointer value is
printf( "%p\n", (void *) x );
In the declaration
int *x;
the initial value of x is indeterminate - it could be anything, from 0x00000000 to 0x00000010 (16) to 0xDEADBEEF to anything else.
There's nothing magic about pointer variables - they store values of a specific type, like an int variable stores integer values and double variable stores floating-point values.
Pointer declaration syntax and operations on pointers are a little non-intuitive and hard to grasp at first, but pointer values themselves are relatively simple things to understand; they're just addresses1 of objects (or functions) in memory.
There's no single pointer type - an int * is a distinct type from a double *, which is a distinct type from a char *, etc. Different pointer types may have different sizes or representations, but on platforms like x86 they all have the same representation.
In a declaration, the presence of a unary * in the declarator means the variable has pointer type:
T *p; // p is a pointer to T
T *ap[N]; // ap is an array of pointers to T
T (*pa)[N]; // pa is a pointer to an array of T
T *fp(); // fp is a function returning a value of type pointer to T
T (*pf)(); // pf is a pointer to a function returning a value of type T
T **pp; // pp is a pointer to pointer to T - it stores the address of
// an object of type T *
In an expression, the presence of the unary * operator means we want to dereference the pointer and obtain the value of the thing it points to:
int x = 10;
int *p = &x; // save the address of x in p
printf( "%d\n", *p ); // print the value stored in x by dereferencing p
More properly, they're abstractions of addresses. Whether those addresses are physical or virtual depends on the environment you're operating in.

Typecasting the Reference of a Double Variable

I have a question about typecasting the reference of a variable of type double. What is exactly happening when &d becomes typecasted into an unsigned char*? How is typecasting the address of a variable valid and what is it actually doing?
#include <stdio.h>
int main(void) {
// examining object representation is a legitimate use of cast
double d = 3.14;
printf("The double %.2f(%a) is: ", d, d);
for(size_t n = 0; n < sizeof d; ++n)
printf("0x%02x ", ((unsigned char*)&d)[n]); // <--
}
And how do the array brackets work in this case?
&d represents a pointer to the location at which the value of the double is stored.
A pointer is simply a memory address (likely a 64-bit value) which identifies a location in memory, regardless of the type of data that is being pointed to.
This makes the cast from a double * to an unsigned char * possible as the representation of both is simply a word of memory. The array notation then dereferences this pointer and adds n times the size of a char (1 byte), and then reads the next char-many bits.
The array notation a[n] is equivalent to *(a+n). It is simply adding an offset to the pointer referred to by a.

Printing Pointer Data with Printf in C

My understanding is that when you declare a pointer, say int *a = 5, a is the pointer, and *ais the int pointed to - so the * indicates you're accessing the pointer data. (And the & is accessing the address). Hopefully this is correct?
How come when I'm doing printf it doesn't seem to work the way I want?
int main()
{
int *a = 5;
printf("%d\n",a);
return 0;
}
This gives me the correct result, which I didn't expect. When I did *a instead of a in the printf, it failed, which I'm confused with?
Nopes, int *a = 5; does not store an int value of 5 into the memory location pointed by a, the memory location itself is 5 (which is mostly invalid). This is an initialization statement, which initializes the variable a which is of type int * (a pointer) to 5.
For ease of understanding, consider the following valid case
int var = 10;
int *ptrVar = &var;
here, ptrVar is assigned the value of &var, the pointer. So, in other words, ptrVar points to a memory location which holds an int and upon dereferencing ptrVar, we'll get that int value.
That said, in general,
printf("%d\n",a);
is an invite to undefined behavior, as you're passing a pointer type as the argument to %d format specifier.
The declaration int *a does declare a to be a pointer. Thus, the declaration
int *a = 5;
initializes a with the value 5. Just like how
int i = 5;
would initialize i with the value 5.
There are very few situations where you would want to initialize a pointer variable with a literal value (other than 0 or NULL). Those would likely be embedded (or otherwise esoteric) applications where certain addresses have a defined meaning on a particular platform.

Distance between arbitrary pointers

I am trying to print the distance between two pointers, but I have found that sometimes the code doesn't work well.
#include <stdio.h>
#include <math.h>
/**
* Print the distance between 2 pointers
*/
void distance(int * a0, int * a1){
size_t difference = (size_t) a1 - (size_t) a0;
printf("distance between %p & %p: %u\n" ,a0, a1, abs((int) difference));
}
Trying this works perfectly!!
int main(void){
int x = 100;
int y = 3000;
distance(&x, &y);
return 0;
}
printing (example):
distance between 0028ff18 & 0028ff14: 4
But start to going wrong with this code
int main(void){
int x = 100;
int p = 1500;
int y = 3000;
distance(&x, &y);
p = p + 2; // remove unused warning
// &p
return 0;
}
printing (example):
distance between 0028ff18 & 0028ff14: 4
When it has to print 8 because of an integer separating this values!
But if I uncomment //&p, it works again.
It is as if the variable p does not exist until its memory address is used.
I'm using gcc 4.9.3 on windows 7 (64 bits)
p is not used in your program and is likely to be optimized out. Anyway this is implementation details and the compiler is free to even change the order of the x and y objects in memory.
it is as if the variable p not exist until its memory address is used
gcc will optimize away any variables that do not affect the behavior of the program.
Secondly, you cannot assume that variables are laid out in any particular order in memory, and the "distance" between any two may be completely meaningless. The only time you can rely on the distance between two pointers to have any meaning is when they are both pointing to elements within the same array object.
Pointer arithmetic is valid only between pointers to elements of the same array, or one past the end. Going against that will have unpredictable and implementation-defined results. In this case, it seems you have found the answer yourself: gcc is optimizing p away, but in any case, you can't assume any specific order of variables in memory, yet alone do pointer arithmetic.
Also, this:
size_t difference = (size_t) a1 - (size_t) a0;
Should be:
ptrdiff_t difference = a1 - a0;
The correct type for the difference between two pointers is ptrdiff_t (defined in stddef.h). You shouldn't cast the pointers to size_t because pointer values are not necessarily representable in a size_t (if you want a numeric type to convert pointers to, use uintptr_t or intptr_t).
The %p format specifier expects a void *, so you should cast the pointers, and the correct format specifier for ptrdiff_t is %td:
printf("distance between %p & %p: %td\n", (void *) a0, (void *) a1, difference);

why different answers?

Below are 2 programs
First
#include<stdio.h>
void main()
{
int a[5]={1,2,3,4,5};
int *p;
p=&a;
printf("%u %u",p,p+1);
}
Second
#include<stdio.h>
void main()
{
int a[5]={1,2,3,4,5};
printf("%u %u",&a,&a+1);
}
Now, in the two programs..I have printed the values of &a using p in first code and directly in the second..
Why are the results different?
the answer i m getting are.
for first 3219048884 3219048888
for second 3219048884 3219048904
The type of &a is int (*) [5]. Therefore &a+1 is a pointer that's 5 ints further on than a. However the type of p is int *, therefore p+1 is a pointer that's 1 int further on than p.
When I run that, I get this:
1245036 1245040 1245036 1245040
1245036 1245040 1245036 1245056
with the only difference being in the last position, p+1 vs &a+1
p is a pointer to an integer, so p+1 is the address of the next integer. (i.e 4 byte further in memeory)
a is an array of 5 integers, so &a+1 is the address of the next array of 5 integers. (i.e., 20 bytes further in memeory)
In both programs, you are printing the memory addresses of the array.
This can vary each time you run the program. The memory that the OS chooses to give you can be different.
When your program declares an array of 5 integers, The OS promises to give you 5 consecutive integers, it does NOT promise what memory you will get, or that you will get the same memory every time.
You have two programs with different stack frames, no surprise the addresses of local variables are different. Il may change each time you run the program (that's what it does when I try it, code compiled with gcc on Linux).
But you'll get the same values with the program below one except for the last value of the serie (except for the last one, because of the way pointer arithmetic works).
#include<stdio.h>
void main()
{
int a[5]={1,2,3,4,5};
int *p;
p=&a;
printf("%u %u %u %u ",a,a+1,p,p+1);
printf("%u %u %u %u",a,a+1,&a,&a+1);
}
For a (quite) complete explanation of difference between pointers and arrays you can look at my answer here
Your first program is invalid. It is illegal to assign p = &a, since p has type int * and &a has type int (*)[5]. These types are not compatible. If your compiler is loose enough to allow this kind of assignment (did it at least warn you?), it probably interpreted it as p = (int *) &a, i.e. it forcefully reinterprets the value of &a as an int * pointer. Thus, all pointer arithmetic in your first program is int * arithmetic. This is why the first program produces the same output for a+1 and p+1 values.
In the second program the value of &a is not reinterpreted. It keeps its original type ``int ()[5]and it follows the rules of normal pointer arithmetic for typeint ()[5], meaning that when you do&a + 1, the pointer is movedsizeof(int[5])` bytes, as it should. This is why the result is different from the first program.
You should use p = a and not p = &a. An array like a is already assumed a constant pointer. You do not need to dereference it with the & operator.

Resources