Why char value increasing 3? - c

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.

Related

C programming why does the address of char array increment from 0012FF74 to 0012FF75?

Heres the code:
char chararray[] = {68, 97, 114, 105, 110};
/* 1 byte each*/
int i;
printf("chararray intarray\n");
printf("-------------------\n");
for(i = 0; i < 5; i++)
printf("%p\n", (chararray + i));
Output:
chararray
---------
0012FF74
0012FF75
0012FF76
0012FF77
Now im trying to understand this in terms of hexadecimal, bits and bytes.
I understand that a char is 1 byte and its supposed to increment by 1 byte which is 8 bits.
But I dont understand how its only increasing by 1 in hex? 1 hexadecimal only represents 4 bits correct? so Im kind of confused, it seems like its only incrementing by 4 bits.
Any help on clearing this up is greatly appreciated thanks!
It's true that if you represent a byte in hexa then it is made out of 2 hexa digits where each one stands for 4 bits.
However, the addresses you are seeing are addresses of bytes, and not the content of them. Each byte receives its own address, and the addresses are sequential, just like if we gave each byte a number: byte 0, byte 1, byte 2, byte 3,....
The address in a pointer points to a byte, not to a bit. Your pointer is of type char *, so when it is incremented, the address increases by sizeof(char). If, however, you used a different type, such as int, your pointer would increase by sizeof(int) on each increment, even if it is pointing to a char [] array.
On my machine, sizeof(int)==4, for example.
I wrote this code:
#include <stdio.h>
int main()
{
char str[] = "ACBDEFGHIJKLMNOPQRSTUVWXYZ";
int *a = str;
printf("Char\tAddr\n");
while(a <= &str[25])
{
printf("%c\t%p\n", *a, (void *)a);
a++;
}
return 0;
}
Output:
Char Addr
A 00D5F9BC
E 00D5F9C0
I 00D5F9C4
M 00D5F9C8
Q 00D5F9CC
U 00D5F9D0
Y 00D5F9D4
Every fourth character in the string is outputted.
First, pointer arithmetics like (chararray + i), where chararray points to a char (i.e. is of type char*) increases the value of pointer chararray by i * sizeof(char). Note that sizeof(char) is 1 by definition.
Second, a pointer represents a memory address, which is represented by an integral value that indicates a position in an (absolutely or relatively) addressed memory block, e.g. on the heap, on the stack, on some other data segment, ... . Confer, for example, the following statement in this online C standard draft:
6.3.2.3 Pointers
(5) An integer may be converted to any pointer type. ...
(6) Any pointer type may be converted to an integer type. ...
So when viewing the value of a pointer, we can think of an integral value, just like 256 or 1024 (when "viewed" in decimal format), or 0x100 or 0x400 (when viewed in hexadecimal format). Note that 256 in decmial is equivalent to 100 in hexadecimal, and this has nothing to do with bits and bytes.
Adding 1 to an integral value of 256 (or 0x100) gives 257 (or 0x101), regardless of whether this value stands for a position in a memory block or for oranges sold in the department store. So it's all about "outputting" integral values in hex format.
See the following code illustrating this:
int main()
{
char chararray[] = {68, 97, 114, 105, 110};
for(int i = 0; i < 5; i++) {
char *ptr = (chararray + i);
unsigned long ptrAsIntegralVal = (unsigned long)ptr;
printf("ptr: %p; in decmial format: %lu\n", ptr, ptrAsIntegralVal);
}
}
Output:
ptr: 0x7fff5fbff767; in decmial format: 140734799804263
ptr: 0x7fff5fbff768; in decmial format: 140734799804264
ptr: 0x7fff5fbff769; in decmial format: 140734799804265
ptr: 0x7fff5fbff76a; in decmial format: 140734799804266
ptr: 0x7fff5fbff76b; in decmial format: 140734799804267
Using hexadecimal numbers is just another way of representing any number. It has nothing to do with bits and bytes. One byte is 8 bits, no matter if you represent it as hexadecimal number or decimal number. So it just increases by one = 1 Byte = 8 Bits.

Pointers in C with typecasting

#include<stdio.h>
int main()
{
int a;
char *x;
x = (char *) &a;
a = 512;
x[0] = 1;
x[1] = 2;
printf("%d\n",a);
return 0;
}
I'm not able to grasp the fact that how the output is 513 or even Machine dependent ? I can sense that typecasting is playing a major role but what is happening behind the scenes, can someone help me visualise this problem ?
The int a is stored in memory as 4 bytes. The number 512 is represented on your machine as:
0 2 0 0
When you assign to x[0] and x[1], it changes this to:
1 2 0 0
which is the number 513.
This is machine-dependent, because the order of bytes in a multi-byte number is not specified by the C language.
For simplifying assume the following:
size of int is 4 (in bytes)
size of any pointer type is 8
size of char is 1 byte
in line 3 x is referencing a as a char, this means that x thinks that he is pointing to a char (he has no idea that a was actually a int.
line 4 is meant to confuse you. Don't.
line 5 - since x thinks he is pointing to a char x[0] = 1 changes just the first byte of a (because he thinks that he is a char)
line 6 - once again, x changed just the second byte of a.
note that the values put in lines 5 and 6 overide the value in line 4.
the value of a is now 0...0000 0010 0000 0001 (513).
Now when we print a as an int, all 4 bytes would be considered as expected.
Let me try to break this down for you in addition to the previous answers:
#include<stdio.h>
int main()
{
int a; //declares an integer called a
char *x; //declares a pointer to a character called x
x = (char *) &a; //points x to the first byte of a
a = 512; //writes 512 to the int variable
x[0] = 1; //writes 1 to the first byte
x[1] = 2; //writes 2 to the second byte
printf("%d\n",a); //prints the integer
return 0;
}
Note that I wrote first byte and second byte. Depending on the byte order of your platform and the size of an integer you might not get the same results.
Lets look at the memory for 32bit or 4 Bytes sized integers:
Little endian systems
first byte | second byte | third byte | forth byte
0x00 0x02 0x00 0x00
Now assigning 1 to the first byte and 2 to the second one leaves us with this:
first byte | second byte | third byte | forth byte
0x01 0x02 0x00 0x00
Notice that the first byte gets changed to 0x01 while the second was already 0x02.
This new number in memory is equivalent to 513 on little endian systems.
Big endian systems
Lets look at what would happen if you were trying this on a big endian platform:
first byte | second byte | third byte | forth byte
0x00 0x00 0x02 0x00
This time assigning 1 to the first byte and 2 to the second one leaves us with this:
first byte | second byte | third byte | forth byte
0x01 0x02 0x02 0x00
Which is equivalent to 16,908,800 as an integer.
I'm not able to grasp the fact that how the output is 513 or even Machine dependent
The output is implementation-defined. It depends on the order of bytes in CPU's interpretation of integers, commonly known as endianness.
I can sense that typecasting is playing a major role
The code reinterprets the value of a, which is an int, as an array of bytes. It uses two initial bytes, which is guaranteed to work, because an int is at least two bytes in size.
Can someone help me visualise this problem?
An int consists of multiple bytes. They can be addressed as one unit that represents an integer, but they can also be addressed as a collection of bytes. The value of an int depends on the number of bytes that you set, and on the order of these bytes in CPU's interpretation of integers.
It looks like your system stores the least significant byte at a lowest address, so the result of storing 1 and 2 at offsets zero and one produces this layout:
Byte 0 Byte 1 Byte 2 Byte 3
------ ------ ------ ------
1 2 0 0
Integer value can be computed as follows:
1 + 2*256 + 0*65536 + 0*16777216
By taking x, which is a char *, and pointing it to the address of a, which is an int, you can use x to modify the individual bytes that represent a.
The output you're seeing suggests that an int is stored in little-endian format, meaning the least significant byte comes first. This can change however if you run this code on a different system (ex. a Sun SPARC machine which is big-enidan).
You first set a to 512. In hex, that's 0x200. So the memory for a, assuming a 32 bit int in little endian format, is laid out as follows:
-----------------------------
| 0x00 | 0x02 | 0x00 | 0x00 |
-----------------------------
Next you set x[0] to 1, which updates the first byte in the representation of a (in this case leaving it unchanged):
-----------------------------
| 0x01 | 0x02 | 0x00 | 0x00 |
-----------------------------
Then you set x[1] to 2, which updates the second byte in the representation of a:
-----------------------------
| 0x01 | 0x02 | 0x00 | 0x00 |
-----------------------------
Now a has a value of 0x201, which in decimal is 513.

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

#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

Run time Error in the Program of Pointers

#include<stdio.h>
main(){
int b=90;
int* a;
a=&b;
//pointer arith metic
printf("Address a is %d\n",a);
printf("size of integer is %d bytes\n",sizeof(int));
printf("Address a is %d\n",*a);
printf("Address a+1 is %d\n",a+1);
printf("value of a+1 is %d\n",*(a+1));
char *ip;
ip=(char*)&b;
printf("Address ip is %d\n",ip);
}
Output of the Program :
Address a is 1495857868
size of integer is 4 bytes
Address a is 90
Address a+1 is 1495857872
value of a+1 is 1495857868
Address ip is 1495857868
Address ip is 90
1.there is always 4 byte gap between the address of the a+1 position and and
2.The output for the value at *(a+1) and the address of variable b when the
pointer converts to char becomes equal
3.Though the pointer value converts into char it shows full value of the variable
ip=(char*)&b;
printf("Address ip is %d\n",*ip);
the output:Address ip is 90
This:
a + 1
when a has type int * will print the address incremented by the size of one int. This is known as pointer arithmetic and is one of C's most core features when it comes to pointers.
1.there is always 4 byte gap between the address of the a+1 position
Gap bytes is determine by type of pointer: char pointer--> gap bytes are 1 byte, int pointer --> gap bytes are 4 bytes ...
In this case: variable a is int pointer --> Gap bytes are 4 bytes
==>Offset of Address (a+1) and (a) is 4 byte (1495857872 - 1495857868 = 4)
The output for the value at *(a+1) and the address of variable b when the pointer converts to char becomes equal
Value at address (a+1) is can not predic, it base on your system.
I run in my PC, result is:
Address b is: 2665524
value of a+1 is: 2665720
If you change your code a little, Add (a+1) = 5; before: //pointer arith metic*
Then run --> result become:
Address b is: 2665524
value of a+1 is: 5
3.Though the pointer value converts into char it shows full value of the variable
It show full value of the variable because value of b is 90, this value only need 1 byte to store in memory, so when convert it to char (1 byte in memory) you saw that value after convert to char equal with int value.
if you asign b > 255, ex: int b=290;
Then run --> result become:
Value a is: 290
value ip is: 34
You may change :
printf("Address a is %d\n",a);
to
printf("Address a is %p\n",a); //%p is specifically designed for pointers.
Till
printf("Address a+1 is %d\n",a+1);
your code should be fine. But the next statement is problematic
printf("value of a+1 is %d\n",*(a+1));
As a is a pointer a+1 will advance a by the number of bytes int occupies in your system. Then, by doing *(a+1) you're trying to access a memory location which is not assigned for a.(Remember a is meant only to store the address of one integer when you do a=&b;).
When you're try to de-reference a memory location which you have no right to, the behavior is undefined as per C standards.
3.Though the pointer value converts into char it shows full value of the variable
ip=(char*)&b;
The statement Though the pointer value converts into char is wrong.It is just that you're treating the contents in address &b as characters. Then you have:
printf("Address ip is %d\n",*ip);
// Remember you're printing the value not address. So change the print message
Remember that the any data is stored as bits ie zeroes or ones and it is the format specifier that you choose which determines how it is displayed. Here you are printing the contents in the &b as an integer as you have mentioned in %d in printf so you get 90 as the result. Fortunately for you the number 90 is small enough to be contained in one byte.
Suppose you changed the printf to :
printf("Value pointed to by ip is %c\n",*ip); // %d to %c
You should have got
Value pointed to by ip is Z
Here 90 is interpreted as an ASCII code which corresponds to letter Z.

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