#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.
Related
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.
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.
I am trying to see that for a given function, memory allocation on stack segment of memory will happen in contiguous way. So, I wrote below code and I got below output.
For int allocation I see the memory address are coming as expected but not for character array. After memory address 0xbff1599c I was expecting next address to be 0xbff159a0 and not 0xbff159a3. Also, since char is 1 byte and I am using 4 bytes, so after 0xbff159a3 I was expecting 0xbff159a7 and not 0xbff159a8
All memory locations comes as expected if I remove char part but I am not able to get expected memory locations with character array.
My base assumption is that on stack segment, memory will always be contiguous. I hope that is not wrong.
#include <stdio.h>
int main(void)
{
int x = 10;
printf("Value of x is %d\n", x);
printf("Address of x is %p\n", &x);
printf("Dereferencing address of x gives %d\n", *(&x));
printf("\n");
int y = 20;
printf("Value of y is %d\n", y);
printf("Address of y is %p\n", &y);
printf("Dereferencing address of y gives %d\n", *(&y));
printf("\n");
char str[] = "abcd";
printf("Value of str is %s\n", str);
printf("Address of str is %p\n", &str);
printf("Dereferencing address of str gives %s\n", *(&str));
printf("\n");
int z = 30;
printf("Value of z is %d\n", z);
printf("Address of z is %p\n", &z);
printf("Dereferencing address of z gives %d\n", *(&z));
}
Output:
Value of x is 10
Address of x is 0xbff159ac
Dereferencing address of x gives 10
Value of y is 20
Address of y is 0xbff159a8
Dereferencing address of y gives 20
Value of str is abcd
Address of str is 0xbff159a3
Dereferencing address of str gives abcd
Value of z is 30
Address of z is 0xbff1599c
Dereferencing address of z gives 30
Also, since char is 1 byte and I am using 4 bytes, so after 0xbff159a3 I was expecting 0xbff159a7 and not 0xbff159a8
char takes up 1 byte , but str is string and you did not count '\0' which is at the end of string and thus ,char str[]="abcd" takes up 5 bytes.
I think this could be because the addresses are aligned to boundaries(e.g. 8 byte boundary)?.
The allocations are always aligned to boundaries and allocated in chunks
in some OS. You can check using a structure. For example,
struct A
{
char a;
char b;
int c;
};
The size of the struct will not be 6 bytes on a UNIX/LINUX platform.
But it might vary from OS to OS.
Similar thing apply to other data types also .
Moreover, a string just points to an address allocated in a
heap if malloc is used and the allocation logic might vary
from OS to OS. The following is output from Linux box
for the same program.
Value of x is 10
Address of x is 0x7ffffa43a50c
Dereferencing address of x gives 10
Value of y is 20
Address of y is 0x7ffffa43a508
Dereferencing address of y gives 20
Value of str is abcd
Address of str is 0x7ffffa43a500
Dereferencing address of str gives abcd
Value of z is 30
Address of z is 0x7ffffa43a4fc
Dereferencing address of z gives 30
Both answers from #ameyCU and #Umamahesh were good but none was self-sufficient so I am writing my answer and adding more information so that folks visiting further can get maximum knowledge.
I got that result because of concept called as Data structure alignment. As per this, computer will always try to allocate memory (whether in heap segment or stack segment or data segment, in my case it was stack segment) in chunks in such a way that it can read and write quickly.
When a modern computer reads from or writes to a memory address, it will do this in word sized chunks (e.g. 4 byte chunks on a 32-bit system) or larger. Data alignment means putting the data at a memory address equal to some multiple of the word size, which increases the system's performance due to the way the CPU handles memory.
On a 32 bits architecture, computers word size is 4 bytes, so computer will always try to allocate memory with addresses falling in multiple of 4, so that it can quickly read and write in block of 4 bytes. When there are lesser number of bytes then computer does padding of some empty bytes either in start or end.
In my case, suppose I use char str[] = "abc"; then including EOL character '\0' I have requirement of 4 bytes, so there will be no padding. But when I do char str[] = "abcd"; then including EOL character '\0' I have requirement of 5 bytes, now computer wants to allocate in block of 4 so it will add padding of 3 bytes (either in start or end) and hence complete char array will be spanned over 8 bytes in memory.
Since int, long memory requirement is already in multiple of 4 so there is no issue and it gets tricky with char or short which are not in multiple of 4. This explains the thing which I reported - "All memory locations comes as expected if I remove char part but I am not able to get expected memory locations with character array."
Rule of thumb is that if your memory requirement is not in multiple of 4 (for example, 1 short, char array of size 2) then extra padding will be added and then memory allocation will happen, so that computer can read and write quickly.
Below is nice excerpt from this answer which explains data structure alignment.
Suppose that you have the structure.
struct S {
short a;
int b;
char c, d;
};
Without alignment, it would be laid out in memory like this (assuming a 32-bit architecture):
0 1 2 3 4 5 6 7
|a|a|b|b|b|b|c|d| bytes
| | | words
The problem is that on some CPU architectures, the instruction to load a 4-byte integer from memory only works on word boundaries. So your program would have to fetch each half of b with separate instructions.
But if the memory was laid out as:
0 1 2 3 4 5 6 7 8 9 A B
|a|a| | |b|b|b|b|c|d| | |
| | | |
Then access to b becomes straightforward. (The disadvantage is that more memory is required, because of the padding bytes.)
// intialize a char variable, print its address and the next address
char charvar = '\0';
printf("address of charvar = %p\n", (void *)(&charvar));
printf("address of charvar - 1 = %p\n", (void *)(&charvar - 1));
printf("address of charvar + 1 = %p\n", (void *)(&charvar + 1));
// intialize an int variable, print its address and the next address
int intvar = 1;
printf("address of intvar = %p\n", (void *)(&intvar));
printf("address of intvar - 1 = %p\n", (void *)(&intvar - 1));
printf("address of intvar + 1 = %p\n", (void *)(&intvar + 1));
This is a code i found online and here is the concerned output
address of charvar = 0x7fff9575c05f
address of charvar - 1 = 0x7fff9575c05e
address of charvar + 1 = 0x7fff9575c060
address of intvar = 0x7fff9575c058
address of intvar - 1 = 0x7fff9575c054
address of intvar + 1 = 0x7fff9575c05c
My doubt is why the memory address in a computer is stored in a hexadecimal format? We know the size of one char is 8bits or 1 byte, what does 1 byte mean in memory that is the address of the start bit of charvar is 0x7fff9575c05f shouldn't the address of the char+1 be the 0x7fff9575c05f + 8bits be 0x7fff9575c067, but it seems that one memory location in the computer is organised in terms of 8bits or 1 byte. Am i correct?If so why?
The memory is organized in terms of bytes, and pointers point to a specific byte, not to a single bit. The reason is probably that early computers had 8-bit registers/... and usually whole bytes were processed at once. Since the computer was operating on whole bytes, addressing bytes instead of single bits made more sense. It also saves address space, allowing for more memory to be addressed with the same pointer size.
Also the memory addresses are not really stored in hexadecimal format, they are just formatted that way when printed out. Internally in memory they are binary numbers just like all the other numbers a computer works with.
The smallest part of memory you can easily access is a byte, so there would be no use making an address for every bit.
Memory is addressed in bytes rather than bits, you have to accept this as a matter of fact. Once you get a value of a certain byte in a memory you can work with its bits using logical (bitwise) functions or operators, such as &, |, ^, ~ etc. See http://www.cprogramming.com/tutorial/bitwise_operators.html
Moreover, the address is not stored in hexadecimal format, the hexadecimal format is only the format of the number printed to the output. If you used other formatter %d rather than %p in your printf call you will get decadic format. See http://www.cplusplus.com/reference/cstdio/printf/
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