Why is the output 2,0 instead of 2,3? - c

#include<stdio.h>
int main()
{
int arr[3] = {2, 3, 4};
char *p;
p = arr;
p = (char*)((int*)(p));
printf("%d, ", *p);
p = (int*)(p+1);
printf("%d", *p);
return 0;
}
Isn't p = (int*)(p+1) ; pointing to the next element of the array? (viz 3?) So the output should be 2,3. But the output is 2,0. Why?

You are increasing the char pointer p to the next char memory position - that is one of the 0 padding bytes for the number 2, which, being an int takes 4 memory positions (the other 3 filled up with zeros).
In short, just replace char *p; for int *p; and get rid of all the casting at p = (char*)((int*)(p)); - your program should just work.
(To make it working keeping the not-useful casting, change p = (int*)(p+1); for p = (char *) (((int *) p) + 1); so that the increment happens on an integer pointer, not on a char pointer)
In a little-endian memory model, such as used in current PC´s, int numbers each take 4 bytes in memory - the first one being the least significative (so, for numbers smaller than 256 (2 ^ 8), they contain the whole number).
You have in memory, this byte sequence: '02 00 00 00 03 00 00 00 04 00 00 00'
When you use a "char *" pointer, the compiler knows that the size of the char data element is 1 byte. On increasing it, it just proceeds to the neighbouring byte, which is "0".
On the "printf" call, you access the content at "char * p", which is a single byte number - 0, and the compiler pads that value in the call to "printf", so that the function still sees "0" - but in other compielrs and systems, it could print garbage or segfault, since 3 of the bytes expected by the printf's "%d" parameter would not be there.

That's because p is the wrong kind of pointer for the datatype.
When you increment p, it doesn't increase its value by 1 * sizeof(int), it increases it by 1 * sizeof(char).
The contents of arr at the byte level, assuming an int is 4 bytes and little endian byte ordering is:
2 0 0 0 3 0 0 0 4 0 0 0
When p is first set, you have this:
2 0 0 0 3 0 0 0 4 0 0 0
^------ p
When you set p to (int*)(p + 1), you increment p by only 1. The cast doesn't help you here. So you get this:
2 0 0 0 3 0 0 0 4 0 0 0
^------ p
So dereferencing p reads 1 byte at that memory location, so you have 0.
If you wanted to increment p by the size of an int, you need to cast p itself, then add to it:
p = `(int*)(p) + 1`
Then you'll get the result you expect.

This is why type of pointer should be of the same data type as of the data it's pointing to for the sake of Pointer Arithmatics
adding 1 to a pointer of specific data type will add number of bytes to the memory address to which a pointer is currently pointing and now it will be pointing to the p+(x-bytes) address and de referencing it will give you the value at that address
for example
you declare a pointer of type int like
int *p = new int[5];
each element in array(if you populate the array) will be stored in memory with the space of 4 bytes (in address terms and in case of 32bit systems) in memory.
And adding 1 to pointer like p = p+1 will take you to the next element in array which is at 4 byte's address ahead of it.
same is the case for any other type of pointer just with the difference that it will be jumping to that much bytes in address space as of the data type the pointer itself it.
now you can say pointer are just pointing to memory so it should not make any difference whether we declare any type of pointer. Yes that's true but not recommended any time as when you're using pointers , pointer arithmatic is very certain to be used there. For the sake of exact jumps in memory addresses we declare pointers of the same data type as of the data they are pointing to

Related

Why char value increasing 3?

I'm dealing with pointers in C, declaring the integer value as 1025. Then I changed the integer to char. When I increase the char pointer by 1, the char value increases by 3. How is this happening?
#include<stdio.h>
int main(){
int a = 1025;
int *p;
p = &a;
char *p0;
p0 = (char*)p;
printf("Address = %d, value = %d\n",p0,*p0);
printf("Address = %d, value = %d\n",p0+1,*(p0+1));
return 0;
}
When you use a char * to alias an object of another type as you're doing, it allows you to access the byte representation of that object.
The value 1025 can be represented in hex as 0x0401. Your system appears to use little-endian byte ordering to store integers, which means the low order bytes appear first in the representation.
So assuming an int is 32 bits on your system a looks like this in memory:
-----------------------------
a | 0x01 | 0x04 | 0x00 | 0x00 |
-----------------------------
The pointer p0 points to the first byte, so *p0 is 1. Then p0+1 points to the next byte so *(p0+1) is 4.
You are incrementing the pointer to the bytes the integer a is composed from. Incidentally 1025 is composed of two bytes with values 1 and 4 - you can check. 1025 = 4*256 + 1. So once you move from 1 to 4 it looks like it was incremented by 3
If you want to access the next element it can be accessed by incrementing the pointer value, not the char value. Increasing the pointer value will enable that pointer to point towards the next value's address and hence you will be seeing the value at the address.
Your output shows what is happening:
Address = 1204440828, value = 1
Address = 1204440829, value = 4
Notice that the address of what you are printing is changing by one. So you are not adding 1 to a you are looking at the value in the location a + 1.
UPDATE: As a clarification: the pointer is pointing to an int but you are printing it as a series of byte values. So the fact that the first byte of the value 1025 happens to decode to 1 If you change a to some other value, you will get somewhat random output. Try changing int a = 1035 and you will get 11 and 4 instead of 1 and 4.

Char pointer to integer array

int main()
{
int x[] = {1, 2, 3};
char *p = &x;
printf("%d", *(p+1));
return 0;
}
I run the code in codeblocks and it is giving 0 as output.
If I I change p as int pointer then its giving 2 as output.
int main()
{
int x[] = {1, 2, 3};
int *p = &x;
printf("%d", *(p+1));
return 0;
}
Why so?
When p is declared as a pointer to char, it is expected to point at data with size of 1 byte. So (p + 1) increments p by 1 byte.
Since an int is at least 4 bytes long, (p + 1) is likely pointing to the second of the higher order bytes of 1, which is still 0.
If you wanted it to have identical output, you would do something like that
printf("%d\n", *(p + sizeof(int)));
But it's best to avoid such code and compile with the -Wall flag, which would definitely produce a warning in your case.
Assume sizeof(int) is 16 bits. 2 in binary is 00000000 00000010.
sizeof(char) is 8 bits.
Little and big endian are two ways of storing multibyte data-types.
Consider the following code:
int i = 2;
char c = (char)&i;
if ((*c)==2)
printf("Little endian");
else //if *c is 0
printf("Big endian");
From this code you can conclude that Big Endian will store 2 as 00000000 00000010. But Little Endian will store it as 00000010 00000000. , So zero as output would mean first 8 bits are zero, so system is Big Endian. Had it been using Little Endian, answer would be 2 as a char p is supposed to point 8 bits only.
Actually, declaring the data type of pointer means to specify how any bits do you want it to refer and how many bits it will jump when incremented.
If in this example, as p is a char pointer, *(p+1) will refer 00000010 in Big endian and 00000000 in Little Endian.
Your compiler may be using 32 bit for interger, so i think in both cases *(p+1) will give 0. (as 2 => 00000000 00000000 00000000 00000010 2nd byte from either side is 0)
Refer to this: `#include
int main()
{
int x[] = {1, 2, 3};
char *p = &x;
printf("%d\n", *p);
printf("%d\n", *(p+1));
printf("%d\n", *(p+2));
printf("%d\n", *(p+3));
printf("%d\n", *(p+4));
printf("%d\n", *(p+5));
printf("%d\n", *(p+6));
printf("%d\n", *(p+7));
printf("%d\n", *(p+8));
return 0;
}`
Output:
1
0
0
0
2
0
0
3
To have a look from a slightly different angle, about the binary + operator, chapter 6.5.6, paragraph 8 of C99 standard says, [emphasis mine]
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. In other words, if the expression P points to the i-th element of an array object, the expressions (P)+N (equivalently, N+(P)) and
(P)-N (where N has the value n) point to, respectively, the i+n-th and i−n-th elements of the array object, provided they exist.
So, in your First case, p is of type char * and (p + 1) gives a result as a pointer which is incremented by sizeof(char)[that's 1 byte, most of the cases] and hence points to the 2nd element of the char array held by p. Since actually, the array held by p is of type int [Let's say 4 bytes of length, in a 32 bit system], so as per the value stored, [1 getting stored as 0000 0000 0000 0001], the *(p+1) prints out 0.
OTOH, in your second case, p is of type int * and (p + 1) gives a result as a pointer which is incremented by sizeof(int) and hence points to the 2nd element of the int array held by p. Since actually, the array held by p is of type int, so as per the value stored, [int x[] = {1, 2, 3};], the *(p+1) prints out 2.
When you increment a pointer, it moves by the size of the thing it is pointing to.
Let's say you have 16 bit integers. In binary, the number one is: 0000 0000 0000 0001
A char pointer can only point to 8 bits at a time: 0000 0000

Assignment of pointers?

int arr[]={1,2,3};
char* p;
p=arr;
This is a fragment of a program and it works.
Can anyone explain how can an int variable address be assigned to char pointer?
This works, because size of char pointer is the same as size of an int pointer. However, when some pointer arithmetic will be applied, you won't get valid results. It means that if you would like to access second element of your array - p[1] then only one byte would added to the p address. If p would be of type int, then 4 byte would be added (since that's the size of int) and second element would be accessed properly.
#include <stdio.h>
int main(void)
{
int arr[] = {1,2,3};
char* p;
p = arr;
printf("%d\n", p[0]);
printf("%d\n", p[1]);
int* pp = arr;
printf("%d\n", pp[0]);
printf("%d\n", pp[1]);
return 0;
}
output:
1
0 - as you can see that is not the value from arr[1]
1
2
As I have intel processor, which is in little endian, arr[0] in memory is stored as following:
01 00 00 00
^
p[0]
p[1] which is equivalent to *(p + 1), will add one byte to p pointer, because size of p is char.
01 00 00 00
^
p[1]
and printf("%d\n, p[1]); gives 0. Note that if you were on big endian machine, the result of printing p[0] would be different (e.g. 0).
However, your compiler should warn you about what you're doing.
warning: assignment from incompatible pointer type [enabled by
default]
When you assign a char point to the address of integer array, many things can happen, depending on the size of the integer. Below is the memory location of the array in compile under 32 bit windows OS. You may also want to cast it p=(char*)arr.
01 00 00 00 02 00 00 00 03 00 00 00
int arr[]={1,2,3};
// arr[0] = 1;
// arr[1] = 2;
// arr[2] = 3;
char* p;
p=(char*)arr;
// p[0] = 1
// p[1] = 0
// p[2] = 0
// p[3] = 0
// p[4] = 2
// p[5] = 0
// p[6] = 0
// p[7] = 0
// p[8] = 3
// p[9] = 0
// p[10] = 0
// p[11] = 0
Your code is invalid. In C language an int * pointer cannot be assigned to a char * pointer without an explicit conversion. C language prohibits assignment of incompatible pointer types. (I.e. it prohibits implicit conversion between such types). Your compiler probably issued a diagnostic message telling you exactly the same thing. Your code contains constraint violation - it is not a valid C code.
This conversion was legal a long time ago, in archaic non-standardized versions of C language. For that reason, by default C compilers are rather permissive with regard to invalid code of this kind. They issue diagnostic messages as "warnings", but continue to compile the code, which misleads some people into believing that the code is valid.
Many C compilers offer you additional options that make them more explicit in detecting such errors. For example, in GCC you have to specify -pedantic-errors switch to have this constraint violation reported with an "error" message.
If your compiler accepted the code, its behavior is the same as if you wrote p = (char *) arr, i.e. it makes p point to the beginning of the arr array. That's all there is to it. If you attempt to access the array data through pointer p, you will simply reinterpret the memory occupied by arr as a sequence of chars. What you will see there will depend on many implementation-dependent factors. (I.e. there are no universal answers to your "Why do I see 0 there? Why do I see 2 there?" questions.) For example, the reinterpreted data will look different between big-endian and little-endian platforms.
Yes you can assign a address of variable of any type to pointer of any type (however you may get a warning about assigning incompatible pointer type). This is because sizeof pointer of any type is same.
For Example:-
int main(void)
{
char *c;
int *i;
float *f;
printf("%d %d %d",sizeof(c),sizeof(i),sizeof(f)); // Output: 4 4 4
}
Side effect of this:
Consider the following example:
int main(void)
{
int i1=127;
int i2=128;
char *c1=&i1;
char *c2=&i2;
printf("%d %d",*c1,*c2); //Output : 127 -128
}
In order to understand this output you need to consider binary values of variables.
Lets start with i1:- Binary value of i1 is
00000000 00000000 00000000 01111111
and by assigning address of this memory to char pointer causes char pointer c1 to point to first byte (Little Endian Method) .
Now binary value of i2 is
00000000 00000000 00000000 10000000
here again c2 points to first byte but why output is -128?
because first byte is 10000000 that sign bit is 1 which means number is negative
now perform a reverse operation of 2's complement
10000000 ---> 01111111(minus one) --->10000000(one's complement)
Your compiler should give you a warning that this is not compatible.
After assignment , lets say address of arr is 1000, arr[0] will be at address 1000, arr[1] will be at address 1004 and arr[2] will be at address 1008
Now p points to arr, so it points to address 1000, so every time you want to access arr[1] you will have to use *(p + 4) since char is 1 byte only (Also care should be taken if its a little endian or big endian machine)
Though its incompatible you can use it but you should be carefull when you use this assignment.
gdb output.
(gdb) p *p
$8 = 1 '\001'
(gdb) p *(p+1)
$9 = 0 '\000'
(gdb) p *(p+2)
$10 = 0 '\000'
(gdb) p *(p+3)
$11 = 0 '\000'
(gdb) p *(p+4)
$12 = 2 '\002'
(gdb) p *(p+5)
$13 = 0 '\000'
(gdb) p *(p+6)
$14 = 0 '\000'
(gdb) p *(p+7)
$15 = 0 '\000'
(gdb) p *(p+8)
$16 = 3 '\003'

C programme return 0 while the pointer point to value 3

I thought at the end of the programme, il will print 3 but in fact it is 0.
Can anyone explain how it is happening ?
Here is the code :
int arr[3] = {2, 3, 4};
char *p;
p = arr;
p = (char*)((int*)(p)); // two conversion, means nothing, omit
printf("%d, ", *p); // point to 2,
p = (int*)(p+1); // point to 3 ?
printf("%d", *p);
return 0;
You are treating an array of integers like an array of chars. The line that is marked as "means nothing" actually means a lot.
When you increment char* p by one, you shift your pointer one byte, but in order to point to the arr[1] you need to increment it sizeof(int) bytes. Declare p as int* p, then p+1 will do what you need.
Since p is of type char, p+1 points to one byte past the start of the first integer. So when you read one byte by dereferencing p, you are reading a position in the integer array that contains a zero byte.
If you increment a pointer, it is incremented by its type's size. Here p is character pointer, and If you increment p it points to next character. As character is of 1 byte, p+1 points to next byte to that pointed by p. If p had been an integer pointer, p+1 would point to next integer i,e 3 in your code.
What's going on?
The following lines print char content (here *p) in int format.
char *p;
printf("%d, ", *p);
It prints 2 because the (current) machine is little-endian (e.g. x86). If this code is run on a big-endian machine, it would print 0. [For endian-ness, see http://en.wikipedia.org/wiki/Endianness ]
Exercise: If the array initialization is changed to the following, what is the expected print output?
int arr[3] = {0x1a2b3c4d, 3, 4};
Pointer increments
Let's say we have
char * pc = 0xA0;
int * pi = 0xB0;
pc += 1; // pc = ?
pi += 1: // pi = ?
What are the new values of pc and pi?
Since pc is a pointer to char, the + 1 increments pc by sizeof(char), which is 1.
However, since pi is a pointer to int, the + 1 increments pi by sizeof(int). In 32 bit system, sizeof(int) is typically 4, whereas in a 64 bit system, sizeof(int) is typically 8.
pc += 1; // pc = 0xA1
pi += 1: // pi = perhaps 0xB4 or 0xB8
Word of Caution
It is okay to experiment for knowledge and curiosity sake, but in real code, accessing the bytes of an int by casting it to char * is not a good idea, it leads to all sorts of endian-portability issues.

Which of the following is the correct output for the program given below?

if the machine is 32bit little-endianess and the sizeof(int) is 4 byte.
Given the following program:
line1: #include<stdio.h>
line2: {
line3: int arr[3]={2,3,4};
line4: char *p;
line5: p=(char*)arr;
line6: printf("%d",*p);
line7: p=p+1;
line8: printf("%d\n",*p);
line9: return 0;
}
What is the expected output?
A: 2 3
B: 2 0
C: 1 0
D: garbage value
one thing that bothering me the casting of the integer pointer to an character pointer.
How important the casting is?
What is the compiler doing at line 5? (p = (char *) arr;)
What is happening at line 7? (p = p + 1)
If the output is 20 then how the 0 is being printed out?
(E) none of the above
However, provided that (a) you are on a little-endian machine (e.g. x86), and (b) sizeof(int) >= 2, this should print "20" (no space is printed between the two).
a) the casting is "necessary" to read the array one byte at a time instead of as a series of ints
b) this is just coercing the address of the first int into a pointer to char
c) increment the address stored in p by sizeof(char) (which is 1)
d) the second byte of the machine representation of the int is printed by line 8
(D), or compiler specific, as sizeof(int) (as well as endianness) is platform-dependent.
How important the casting is?
Casting, as a whole is an integral (pun unintended) part of the C language.
and what the compilar would do in line number5?
It takes the address of the first element of arr and puts it in p.
and after line number 5 whats going on line number7?
It increments the pointer so it points to the next char from that memory address.
and if the output is 2 0 then how the 0 is being printed by the compiler?
This is a combination of endanness and sizeof(int). Without the specs of your machine, there isn't much else I can do to explain.
However, assuming little endian and sizeof(int) == 4, we can see the following:
// lets mark these memory regions: |A|B|C|D|
int i = 2; // represented as 0x02000000
char *ptr = (char *) &i; // now ptr points to 0x02 (A)
printf("%d\n", *ptr); // prints '2', because ptr points to 0x02 (A)
ptr++; // increment ptr, ptr now points to 0x00 (B)
printf("%d\n", *ptr); // prints '0', because ptr points to 0x00 (B)
1.important of casting:-
char *p;
this line declare a pointer to a character.That means its property is it can de-reference
only one byte at a time,and also displacement are one one byte.
p=(char*)arr;
2. type casting to char * is only for avoid warning by compiler nothing else.
If you don't then also same behavior.
as pointer to a character as I already write above p=p+1 point to next byte
printf("%d\n",*p);
%d is formatting the value to decimal integer so decimal format shown
here *p used and as per its property it can de-reference only one byte.So now memory organisation comes into picture.
that is your machine follows little endian/LSB first or big endian/MSB first
as per your ans your machine follow little endian.So first time your ans is 0.
Then next byte must be zero so output is 0.
in binary:
2 represented as 00-00-00-02(byte wise representation)
but in memory it stores like
02-00-00-00 four bytes like this
in first memory byte 02
and in 2nd memory byte 00

Resources