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.
Related
So this expression comes out to 4:
int a[] = {1,2,3,4,5}, i= 3, b,c,d;
int *p = &i, *q = a;
char *format = "\n%d\n%d\n%d\n%d\n%d";
printf("%ld",(long unsigned)(q+1) - (long unsigned)q);
I have to explain it in my homework and I have no idea why it's coming out to that value. I see (long unsigned) casting q+1, and then we subtract the value of whatever q is pointing at as a long unsigned and I assumed we would be left with 1. Why is this not the case?
Because q is a pointer the expression q+1 employs pointer arithmetic. This means that q+1 points to one element after q, not one byte after q.
The type of q is int *, meaning it points to an int. The size of an int on your platform is most likely 4 bytes, so adding 1 to a int * actually adds 4 to the raw pointer value so that it points to the next int in the array.
Try printing the parts of the expression and it becomes a bit clearer what is going on.
printf("%p\n",(q+1));
printf("%p\n",q);
printf("%ld\n",(long unsigned)(q+1));
printf("%ld\n",(long unsigned)q);
It becomes more clear that q is a pointer pointing to the zeroth element of a, and q+1 is a pointer pointing to the next element of a. Int's are 4 bytes on my machine (and presumably on your machine), so they are four bytes apart. Casting the pointers to unsigned values has no effect on my machine, so printing out the difference between the two gives a value of 4.
0x7fff70c3d1a4
0x7fff70c3d1a0
140735085269412
140735085269408
It's because sizeof(int) is 4.
This is an esoteric corner of C that is usually best avoided.
(If it doesn't make sense yet, add some temporary variables).
BTW, the printf format string is incorrect. But that's not why it's outputting 4.
#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
I wrote a simple c program like this
#include<stdio.h>
void main()
{
int a=10;
int *p;int **q;
p=&a,q=&p;
printf("size of p %d\n",sizeof(p));
printf("%d\t%d\n",p,q);
printf("%d\t%d",++p,++q);
}
output is like this
size of p 8
55611340 55611320
55611344 55611328
if i am execcuting same binary once more i am getting like this
size of p 8
-385904884 -385904904
-385904880 -385904896
why output is varying in reverse way second time . O/p is randomly varying in reverse way every time. Can any please tell me why this one happens
The %d format specifier is for printing signed integers, not pointers. Using the incorrect format specifier invokes undefined behavior.
To properly print pointers, use the %p format specifier and cast the pointer in question to void * (one of the rare time casting to/from void * is required).
printf("%p\t%p\n", (void *)p, (void *)q);
printf("%p\t%p", (void *)(++p), (void *)(++q));
Also, use the %zu format specifier for printing a size_t (which the sizeof operator returns).
printf("size of p %zu\n",sizeof(p));
Im going to try answer the question I think you are asking which is this:
Why are the numbers not what I expect?
I got some deeper insight into your program by modifying it thus:
#include<stdio.h>
void main()
{
int a=10;
int *p;int **q;
p=&a,q=&p;
printf("size of p %d\n",sizeof(p));
printf("size of q %d\n", sizeof(q));
printf("size of int %d\n", sizeof(int));
printf("size of int* %d\n", sizeof(int*));
printf("size of int** %d\n", sizeof(int**));
printf("%d\t%d\n",p,q);
printf("%d\t%d",++p,++q);
}
I get the following results:
size of p 8
size of q 8
size of int 4
size of int* 8
size of int** 8
1741631236 1741631240
1741631240 1741631248
The interpretation of this is that p is a pointer to an int, which is 4 bytes in size. When you increment a pointer-to-int the pointer gets incremented by 4. However q is a pointer-to-pointer. Now, a pointer is 8 bytes in size, so when you increment a pointer-to-pointer, it gets incremented by 8.
This is exactly what we see in your example output as well: the difference between p and q, before and after the increment, is 4 and 8 respectively.
You created 64 bit app so the size of pointer is 8 bytes
All pointer is ok, It will be clear, if you display pointer value properly (all values will be in hexadecimal):
the only correct way:
printf("%p\t%p\n",p,q);
printf("%p\t%p",++p,++q);
or you may use (do not protected from undefined behavior)
printf("%016llx\t%016llx\n",p,q);
printf("%016llx\t%016llx",++p,++q);
or simple unsigned values
printf("%llu\t%llu\n",p,q);
printf("%llu\t%llu",++p,++q);
Reversed values is because you display integer values (signed), if you display unsigned value or hexadecimal integer the results will be displayed properly.
It looks like % d is used for printing address in code.%d is used for integer variable
so it taking has
INT_MIN Minimum value for a variable of type int. –2147483648
INT_MAX Maximum value for a variable of type int. 2147483647
I wanted to test if I could change the constant pointer that points to the first element of an array in C. While testing I got some strange output that I don't understand:
//Constant pointer to pointer to constant value
void test(int const * * const a) {
//printf("%d", **a); //Program crashes (2)
(*a)++;
}
int main()
{
int a[5] = { 1,2,3,4,5 };
test(&a);
printf("%d", *a); //Prints 5 as output (1)
return 0;
}
I expected the compiler to give an error when I try to compile (*a)++ but instead I can run the code, but when I try to print the element I get a strange value (1).
Then I wanted to print out the value (2) of the first element of the array. When I tried this, the program crashes.
By doing &a you are making a pointer to an array (int (*)[]).
Then when this pointer to array is passed to the test function, it's converted to a pointer to a pointer(int **);
Then (*a)++; is UB.
1. So why 5?
On modern implementation of C like GCC, pointer to a array has the same numerical value as the beginning of the array, so is the address value when the array decays to a pointer: they all are the beginning address of the array.
So, in test, int **a points to the beginning of the array, (*a)++ deferences the pointer as int * and increment the pointer by 1 int element, which is usually implemented as adding the sizeof(int) to the numerical value of the pointer.
Then, 1+sizeof(int) gives you 5.
2. Why it crashed in the second case?
Assuming you are using a 32bit x86 machine, or some machine whose pointer type has the same size as int type, then *a equal to 1. Then further dereferencing the pointer at a memory address at 1 usually gives you a segfault.
The program crashes at the printf because test assumes that when it dereferences a the resulting object is a pointer. If it were one and contained a valid address, the second dereferencing would yield an int object. Alas, a contains the address of the array, which is numerically the address of its first element. The 4 or 8 bytes there are considered an address (because test thinks that *a is a pointer) and the code then tries to access the memory at address 1 in order to print the int value assumed at that address. The address is invalid though, so the program crashes.
Now that we have established that the program considers the data at the beginning of the array a pointer to int, we know what (*a)++ does: it increments the value there by sizeof(int) so that the "pointer" point to the next int "element". I guess an int on your machine is 4 bytes long because 1+4=5, which is printed.
This code is illegal in C, you should get a compiler diagnostic. (If not, turn up your warning level). The results of running any executable produced are meaningless.
The code is illegal because int (*)[5] does not implicitly convert to int const **.
the constant pointer that points to the first element of an array in C
There is no such thing. You misunderstand what arrays are. Arrays are a series of contiguous elements. int a[5] is like int a; except that there are 5 ints instead of 1.
int a; and int a[1]; cause identical memory layout. The only difference is the syntax used to access that memory.
I can't understand the output of this program .
What I get of it is , that , first of all , the pointers p, q ,r ,s were pointing towards null .
Then , there has been a typecasting . But how the heck , did the output come as 1 4 4 8 . I might be very wrong in my thoughts . So , please correct me if I am wrong .
int main()
{
int a, b, c, d;
char* p = (char*)0;
int *q = (int *)0;
float* r = (float*)0;
double* s = (double*)0;
a = (int)(p + 1);
b = (int)(q + 1);
c = (int)(r + 1);
d = (int)(s + 1);
printf("%d %d %d %d\n", a, b, c, d);
_getch();
return 0;
}
Pointer arithmetic, in this case adding an integer value to a pointer value, advances the pointer value in units of the type it points to. If you have a pointer to an 8-byte type, adding 1 to that pointer will advance the pointer by 8 bytes.
Pointer arithmetic is valid only if both the original pointer and the result of the addition point to elements of the same array object, or just past the end of it.
The way the C standard describes this is (N1570 6.5.6 paragraph 8):
When an expression that has integer type is added to or subtracted
from a pointer, the result has the type of the pointer operand. If the
pointer operand points to an element of an array object, and the array
is large enough, the result points to an element offset from the
original element such that the difference of the subscripts of the
resulting and original array elements equals the integer expression.
[...]
If both the pointer operand and the result point to elements of the
same array object, or one past the last element of the array object,
the evaluation shall not produce an overflow; otherwise, the behavior
is undefined. If the result points one past the last element of the
array object, it shall not be used as the operand of a unary *
operator that is evaluated.
A pointer just past the end of an array is valid, but you can't dereference it. A single non-array object is treated as a 1-element array.
Your program has undefined behavior. You add 1 to a null pointer. Since the null pointer doesn't point to any object, pointer arithmetic on it is undefined.
But compilers aren't required to detect undefined behavior, and your program will probably treat a null pointer just like any valid pointer value, and perform arithmetic on it in the same way. So if the null pointer points to address 0 (this is not guaranteed, BTW, but it's very common), then adding 1 to it will probably give you a pointer to address N, where N is the size in bytes of the type it points to.
You then convert the resulting pointer to int (which is at best implementation-defined, will lose information if pointers are bigger than int, and may yield a trap representation) and you print the int value. The result, on most systems, will probably show you the sizes of char, int, float, and double, which are commonly 1, 4, 4, and 8 bytes, respectively.
Your program's behavior is undefined, but the way it actually behaves on your system is typical and unsurprising.
Here's a program that doesn't have undefined behavior that illustrates the same point:
#include <stdio.h>
int main(void) {
char c;
int i;
float f;
double d;
char *p = &c;
int *q = &i;
float *r = &f;
double *s = &d;
printf("char: %p --> %p\n", (void*)p, (void*)(p + 1));
printf("int: %p --> %p\n", (void*)q, (void*)(q + 1));
printf("float: %p --> %p\n", (void*)r, (void*)(r + 1));
printf("double: %p --> %p\n", (void*)s, (void*)(s + 1));
return 0;
}
and the output on my system:
char: 0x7fffa67dc84f --> 0x7fffa67dc850
int: 0x7fffa67dc850 --> 0x7fffa67dc854
float: 0x7fffa67dc854 --> 0x7fffa67dc858
double: 0x7fffa67dc858 --> 0x7fffa67dc860
The output is not as clear as your program's output, but if you examine the results closely you can see that adding 1 to a char* advances it by 1 byte, an int* or float* by 4 bytes, and a double* by 8 bytes. (Other than char, which by definition has a size of 1 bytes, these may vary on some systems.)
Note that the output of the "%p" format is implementation-defined, and may or may not reflect the kind of arithmetic relationship you might expect. I've worked on systems (Cray vector computers) where incrementing a char* pointer would actually update a byte offset stored in the high-order 3 bits of the 64-bit word. On such a system, the output of my program (and of yours) would be much more difficult to interpret unless you know the low-level details of how the machine and compiler work.
But for most purposes, you don't need to know those low-level details. What's important is that pointer arithmetic works as it's described in the C standard. Knowing how it's done on the bit level can be useful for debugging (that's pretty much what %p is for), but is not necessary to writing correct code.
Adding 1 to a pointer advances the pointer to the next address appropriate for the pointer's type.
When the (null)pointers+1 are recast to int, you are effectively printing the size of each of the types being pointed to by the pointers.
printf("%d %d %d %d\n", sizeof(char), sizeof(int), sizeof(float), sizeof(double) );
does pretty much the same thing. If you want to increment each pointer by only 1 BYTE, you'll need to cast them to (char *) before incrementing them to let the compiler know
Search for information about pointer arithmetic to learn more.
You're typecasting the pointers to primitive datatypes rather type casting them to pointers themselves and then using * (indirection) operator to indirect to that variable value. For instance, (int)(p + 1); means p; a pointer to constant, is first incremented to next address inside memory (0x1), in this case. and than this 0x1 is typecasted to an int. This totally makes sense.
The output you get is related to the size of each of the relevant types. When you do pointer arithmetic as such, it increases the value of the pointer by the added value times the base type size. This occurs to facilitate proper array access.
Because the size of char, int, float, and double are 1, 4, 4, and 8 respectively on your machine, those are reflected when you add 1 to each of the associated pointers.
Edit:
Removed the alternate code which I thought did not exhibit undefined behavior, which in fact did.