How to understand pointer behavior for this code snippet - c

I know this code doesn't make much sense but I just wanted to know how the pointers in this code are working.
int main()
{
int a=2;
int *b = &a;
void* c = (void*)b;
printf("\n%d %d %d %d %d %d",a,&a,*b,b,c,*(int*)(c+1));
*(int*)(c+1) = 3;
printf("\n%d %d %d %d %d %d",a,&a,*b,b,c,*(int*)(c+1));
return 0;
}
The output is given below.
2 -1244818996 2 -1244818996 -1244818996 -872415232
770 -1244818996 -1244818996 -1244819200 -1244818996 3
I ran this code many times, and the output for pointer values were different (obviously) but the values of a as "2" and "770" remained same for (int)(c+1) = 3 and changed only when i changed c+1 to c+2 or c+3, or changed "3" to some other value. So I want to know what is the link between this a=2 changing to a=770 with (int)(c+1) = 3, and how is it changing.

Here's a lot of undefined behavior.
printf("\n%d %d %d %d %d %d",a,&a,*b,b,c,*(int*)(c+1));
a will print 2.
&a will print the low sizeof(int) bytes of the address, as an address has 8 bytes on 64 bit PCs.
*b will print 2.
b is the same as with &a.
c is the same as &a and b.
*(int*)(c+1) will "construct" an int, from three bytes of a in memory and one byte, that is after a.
printf("\n%d %d %d %d %d %d",a,&a,*b,b,c,*(int*)(c+1));
You changed a part of a, because you changed c, that points to some bytes of a, so the values change,too.

Code is very much unportable, but basically, you have a little endian machine there. I'll assume sizeof(int) == 4 here. Another assumption is that void pointer arithmetic works same as char.
int a = 2; puts 0x02 0x00 0x00 0x00 at address of a.
Later *(int*)(c+1) = 3; puts 0x03 0x00 0x00 0x00 at address of a + 1 byte, so you get 0x02 0x03 0x00 0x00 0x00.
Now if you interpret a as an int again, it's (I'm using ** for exponentiation)2*2**0 + 3*2**8 + 0*2**16 + 0*2**24 = 2 + 3*256 = 770.
Using a debugger and looking at raw memory might help make things clearer.

Related

What happen when we do AND operation of 4 byte number with 2 byte number

I am trying to write a piece of code to extract every single byte of data out of a 4 byte integer
after little bit of searching i actually found the code with which this can be achieved , but i am just curious to know why it behaves the way output is created , below is the code
#include <stdio.h>
int getByte(int x, int n);
void main()
{
int x = 0xAABBCCDD;
int n;
for (n=0; n<=3; n++) {
printf("byte %d of 0x%X is 0x%X\n",n,x,getByte(x,n));
}
}
// extract byte n from word x
// bytes numbered from 0 (LSByte) to 3 (MSByte)
int getByte(int x, int n)
{
return (x >> (n << 3)) & 0xFF;
}
Output:
byte 0 of 0xAABBCCDD is 0xDD
byte 1 of 0xAABBCCDD is 0xCC
byte 2 of 0xAABBCCDD is 0xBB
byte 3 of 0xAABBCCDD is 0xAA
the result is self explanatory but why the compiler didn't converted 0xFF into 0x000000FF , since it has to perform AND operation with a 4 byte number and instead generated the output consisting of only 1 byte of data and not 4 byte of data.
The compiler did convert 0xFF to 0x000000FF. Since the value is an integer constant, 0xFF gets converted internally to a 32-bit value (assuming that your platform has a 32-bit int).
Note that the values you get back, i.e. 0xDD, 0xCC, 0xBB, and 0xAA, are also ints, so they have leading zeros as well, so you actually get 0x000000DD, 0x000000CC, and so on. Leading zeros do not get printed automatically, though, so if you wish to see them, you'd need to change the format string to request leading zeros to be included:
for (n=0; n<=3; n++) {
printf("byte %d of 0x%08X is 0x%08X\n", n, x, getByte(x,n));
}
Demo.
The output is a 4-byte number, but printf("%X") doesn't print any leading zero digits.
If you do printf("foo 0x%X bar\n", 0x0000AA) you'll get foo 0xAA bar as output.
0xFF and 0x000000FF are both exactly the same thing, by default the formatting will drop the leading 0's if you want to print them in your output, you just need to specify it:
printf("byte %d of 0x%X is 0x08%X\n",n,x,getByte(x,n));
But since you are printing Bytes I'm not quite sure why you would expect the leading 0's.

Data stored with pointers

void *memory;
unsigned int b=65535; //1111 1111 1111 1111 in binary
int i=0;
memory= &b;
for(i=0;i<100;i++){
printf("%d, %d, d\n", (char*)memory+i, *((unsigned int * )((char *) memory + i)));
}
I am trying to understand one thing.
(char*)memory+i - print out adress in range 2686636 - 2686735.
and when i store 65535 with memory= &b this should store this number at adress 2686636 and 2686637
because every adress is just one byte so 8 binary characters so when i print it out
*((unsigned int * )((char *) memory + i)) this should print 2686636, 255 and 2686637, 255
instead of it it prints 2686636, 65535 and 2686637, random number
I am trying to implement memory allocation. It is school project. This should represent memory. One adress should be one byte so header will be 2686636-2586639 (4 bytes for size of block) and 2586640 (1 byte char for free or used memory flag). Can someone explain it to me thanks.
Thanks for answers.
void *memory;
void *abc;
abc=memory;
for(i=0;i<100;i++){
*(int*)abc=0;
abc++;
}
*(int*)memory=16777215;
for(i=0;i<100;i++){
printf("%p, %c, %d\n", (char*)memory+i, *((char *)memory +i), *((char *)memory +i));
}
output is
0028FF94,  , -1
0028FF95,  , -1
0028FF96,  , -1
0028FF97, , 0
0028FF98, , 0
0028FF99, , 0
0028FF9A, , 0
0028FF9B, , 0
i think it works. 255 only one -1, 65535 2 times -1 and 16777215 3 times -1.
In your program it seems that address of b is 2686636 and when you will write (char*)memory+i or (char*)&b+i it means this pointer is pointing to char so when you add one to it will jump to only one memory address i.e2686637 and so on till 2686735(i.e.(char*)2686636+99).
now when you are dereferencing i.e.*((unsigned int * )((char *) memory + i))) you are going to get the value at that memory address but you have given value to b only (whose address is 2686636).all other memory address have garbage values which you are printing.
so first you have to store some data at the rest of the addresses(2686637 to 2686735)
good luck..
i hope this will help
I did not mention this in my comments yesterday but it is obvious that your for loop from 0 to 100 overruns the size of an unsigned integer.
I simply ignored some of the obvious issues in the code and tried to give hints on the actual question you asked (difficult to do more than that on a handy :-)). Unfortunately I did not have time to complete this yesterday. So, with one day delay my hints for you.
Try to avoid making assumptions about how big a certain type is (like 2 bytes or 4 bytes). Even if your assumption holds true now, it might change if you switch the compiler or switch to another platform. So use sizeof(type) consequently throughout the code. For a longer discussion on this you might want to take a look at: size of int, long a.s.o. on Stack Overflow. The standard mandates only the ranges a certain type should be able to hold (0-65535 for unsigned int) so a minimal size for types only. This means that the size of int might (and tipically is) bigger than 2 bytes. Beyond primitive types sizeof helps you also with computing the size of structures where due to memory alignment && packing the size of a structure might be different from what you would "expect" by simply looking at its attributes. So the sizeof operator is your friend.
Make sure you use the correct formatting in printf.
Be carefull with pointer arithmetic and casting since the result depends on the type of the pointer (and obviously on the value of the integer you add with).
I.e.
(unsigned int*)memory + 1 != (unsigned char*)memory + 1
(unsigned int*)memory + 1 == (unsigned char*)memory + 1 * sizeof(unsigned int)
Below is how I would write the code:
//check how big is int on our platform for illustrative purposes
printf("Sizeof int: %d bytes\n", sizeof(unsigned int));
//we initialize b with maximum representable value for unsigned int
//include <limits.h> for UINT_MAX
unsigned int b = UINT_MAX; //0xffffffff (if sizeof(unsigned int) is 4)
//we print out the value and its hexadecimal representation
printf("B=%u 0x%X\n", b, b);
//we take the address of b and store it in a void pointer
void* memory= &b;
int i = 0;
//we loop the unsigned chars starting at the address of b up to the sizeof(b)
//(in our case b is unsigned int) using sizeof(b) is better since if we change the type of b
//we do not have to remember to change the sizeof in the for loop. The loop works just the same
for(i=0; i<sizeof(b); ++i)
{
//here we kept %d for formating the individual bytes to represent their value as numbers
//we cast to unsigned char since char might be signed (so from -128 to 127) on a particular
//platform and we want to illustrate that the expected (all bytes 1 -> printed value 255) occurs.
printf("%p, %d\n", (unsigned char *)memory + i, *((unsigned char *) memory + i));
}
I hope you will find this helpfull. And good luck with your school assignment, I hope you learned something you can use now and in the future :-).

((char) 257) prints 1 in C?

I am vastly confused. I'm having a headache.
I'm new to C.
#include<stdio.h>
int main()
{
int i = 257;
int *iPtr = &i;
printf("val 1: %d \t val 2: %d \n\n",*( (char*)iPtr ), *( (char*)iPtr+1) );
int iptr_alias = iPtr;
int and_val = iptr_alias & 255;
printf("Value of iPtr (aka address of i): %d \n\n", iPtr);
printf("Value at location pointed to by iPtr using %%c: %c \n\n",*iPtr); //gives weird character
int f = 257;
int *fptr = &f;
printf("char starred fptr: %d \t charred 257: %d \n\n",*((char*)fptr), ((char)257) );
// i know the above is obvious.
system("PAUSE");
}
My questions:
1. Apparently *( (char*) iPtr ) = 257 & 255 = 1 (bitwise and operation).
And (char)*iPtr is the same also . But it doesn't print 1 if i use %c modifier. Why?
2. And why *( (char*) iPtr+1 ) = 1 ??
I'm so confused with all this (which i wrote myself to clear confusion, but it worked otherwise..)
((char)257) gives 1 using %d or %o or %x for that matter. %c gives some weird ASCII character
I mean, when i do printf(" %c ", 257) , then i don't get 1, instead, I get a weird ASCII character. Why?
In the actual problem, I was supposed to determine what would be printed as val 1 and val 2.
I maybe overlooking anything stupidly simple, but i'm really feeling confused and tired about this mess.
Please help.
Remember that a char is only 8 bits, and can therefore represent number from 0 to 255. When you print 257 it rolls over and becomes 1 (256 would be zero).
As for why why 257 (i.e. 1) becomes a weird character, I direct you to an ASCII table.
Edit: About signed versus unsigned
In this case, your char type is unsigned. If it were signed then the rollover would have happen at 127 (but due to how signed/unsigned works it would have roll over to -128 and 129 would roll over to -127).
The integer 257 is also 0x101 in hex. On a little-endian machine with 32-bit integers the individual bytes will be 0x01 0x01 0x00 0x00.

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

What is the explaination for this simple pointer program output

I tried to understand the size of address used to store variables and pointers, pointers-pointers and pointers-pointers-pointers. The results are kind of confusing.
Here is the code:
#include <stdio.h>
#include <conio.h>
#include <stdlib.h>
int main(void)
{
char *** ppptr_string = NULL;
int *** ppptr_int = NULL;
double *** ppptr_dbl = NULL;
char c=0; int i=0; double d=0;
printf("\n %d %d %d %d %d\n", sizeof(&ppptr_string),
sizeof(ppptr_string), sizeof(*ppptr_string), sizeof(**ppptr_string),
sizeof(***ppptr_string));
printf("\n %d %d %d %d %d\n", sizeof(&ppptr_int), sizeof(ppptr_int),
sizeof(*ppptr_int), sizeof(**ppptr_int), sizeof(***ppptr_int));
printf("\n %d %d %d %d %d\n", sizeof(&ppptr_dbl), sizeof(ppptr_dbl),
sizeof(*ppptr_dbl), sizeof(**ppptr_dbl), sizeof(***ppptr_dbl));
printf("\n sizeof(char) = %d, sizeof(int) = %d, sizeof(double) = %d",
sizeof(c), sizeof(i), sizeof(d));
printf("\n sizeof(&char) = %d, sizeof(&int) = %d, sizeof(&double) = %d",
sizeof(&c), sizeof(&i), sizeof(&d));
getch();
return 0;
}
Now the confusion. I can see that a variable address is always 2 bytes long on this machine. Regardless of type of the variable and regardless of the whether its a pointer variable. But why do I get size of 4 for so many entries in here? The pointer has size 4 always regardless of the type. The >address< at which the variable is stored is of size 2. And the content pointed to has a sized depending on the type.
Why do I get 4s in the output for sizeof??
My output from Borland C++ 5.02
If you have a type T and a pointer on pointer like T*** ptr, then ptr, *ptr, **ptr are pointers themselves. You're probably working on a 32bit system (or compiling a 32bit application), so sizeof(ptr) == sizeof(*ptr) == sizeof(**ptr):
--- Program output ---
4 4 4 4 1
4 4 4 4 4
4 4 4 4 8
sizeof(char) = 1, sizeof(int) = 4, sizeof(double) = 8
sizeof(&char) = 4, sizeof(&int) = 4, sizeof(&double) = 4
&ptr is an address/a pointer on T***, so its size is 4 too. Only if you dereference the pointer to its maximum level (***ptr) you will have the actual type and not another pointer.
I think what's happening is that you're getting near (16-bit) pointers for local variables, but a pointer declared as type * is a far (32-bit) pointer.
It's a quirk of working on a 16-bit Intel processor (or a 32-bit processor in "real mode"), e.g. in DOS, where you only have access to 1 MB of memory (or 640 kB in practice). The upper 16 bits of a far pointer are a segment (a 64k page in memory), and the lower 16 bits are an offset.
http://en.wikipedia.org/wiki/Real_mode
http://wiki.answers.com/Q/What_are_near_far_and_huge_pointers_in_C
Answerers not able to reproduce this are most likely using a 32-bit (or more) OS on a 32-bit (or more) processor.

Resources