I'm beginner in C Programming and Now learning concepts of Pointers. Here's my code -->>
`#include<stdio.h>
int main()
{
char t='s';
int a=10;
float s=89;
void *ptr;
ptr =&s;
printf("%c\t",*((char*)ptr));
printf("%d\t",*((int*)ptr));
printf("%f\t",*((float*)ptr));
return 0;
}`
My question is When I deferenced a void pointer which points to the Floating Point number into Char then why the output is Blank Space and for Integer it is 1118961664. I wish to know that what's going on in the Byte Level and Is it depends on Alignment of Bytes and Architecture!!
Often, the float s variable is 4 bytes long and its value (89) is represented in IEEE 754 format. For simplicity, let's assume this.
The first printf (char) will use the first byte of the original float variable s (because one C char = 1 byte). Here the first byte means the byte located in the lowest memory position of the 4 bytes of float s. Yes, this is dependent on the machine's byte alignment. The output is blank most likely because the first byte corresponds to an ascii control charater (for example 0).
The second printf, assuming that an int is 4-bytes long in your machine/compiler, will take the same 4 bytes as the third printf but will print them as an integer (note the difference between integers and IEEE 754 floating point numbers). It turns out that the IEEE 754 representation of 89 corresponds to a "1118961664" integer. This will also be dependent on byte alignment.
The third printf is doing the right thing, it will use the bytes where s's value (89) is stored, and interpret them as a floating point number. It should print 89.0. This does not depend on byte alignment.
If the size or representation of floats were different the details would change (how many bytes come from where, and what number is printed by the second printf) but the behavior would be similar. Note also that in principle the first two printf calls have undefined behavior.
float numbers (that is of type float) occupy 4 bytes. In this expression *((char*)ptr)) the first byte of s is interpretated as a character. In expression *((int*)ptr)) all four bytes of s are interpretated as an integer provided that sizeof( int ) equal to 4.
As internal representation of float and int are different you get different vresults.
Related
I was messing around with pointers in C and was trying to read values from the same address using different types of pointers. First I created a double variable and assigned the number 26 to it.
double g = 26;
like so. And then I assigned g's address to a void pointer void *vptr = &g;. after that, I tried to read the value at the address of g as a float by type-casting.
float *atr = (float*) (vptr);. When I tried to print the value of *atr it gave me 0.000000. Then i used pointer to a character since characters are 1 byte and tried to see values of those 8 bytes one by one.
char *t;
t = (char*) vptr;
for (int i = 0; i < 8; i++){
printf("%x t[%d]: %d\n",t+i , i, t[i]);
}
it gave me this output
ffffcbe9 t[1]: 0
ffffcbea t[2]: 0
ffffcbeb t[3]: 0
ffffcbec t[4]: 0
ffffcbed t[5]: 0
ffffcbee t[6]: 58
ffffcbef t[7]: 64
Then I checked binary representation of g which is 01000000 00111010 00000000 00000000 00000000 00000000 00000000 00000000 using this website.
When I convert every byte to decimal individually, first byte becomes 64 and the second is 58.
So it was basically reversed. Then I tried to read as a float again but this time i shifted the address.
atr = (float*) (vptr+4);. I didn't know how many bytes it would shift but coincidentally i discovered that it shifts by one just like char pointers.
This time i printed as printf("%f\n",*atr); and now it gave me 2.906250.
When I checked it's binary representation it was 01000000 00111010 00000000 00000000 which is the first half of the variable g. So I am kind of confused how C is reading values from addresses since it looks like c reads the values from right-end and when i add positive numbers to addresses it shifts towards left-end. I am sorry for any spelling or grammatical mistakes.
The order in which the bytes of an scalar object are stored in C are implementation-defined, per C 2018 6.2.6.1 2. (Array elements are of course stored in ascending order by index, and members of structures are in order of declaration, possibly with padding between them.)
The behavior of using *atr after float *atr = (float*) (vptr); is not defined by the C standard, due to the aliasing rules in C 2018 6.5 7. It is defined to examine the bytes through a char lvalue, as you did with t[i], although which bytes are which is implementation-defined per above.
A proper way to reinterpret some bytes of a double as a float is to copy them in byte-by-byte, which you can do with manual code using a char * or simply float f; memcpy(&f, &g, sizeof f);. (memcpy is specified to work as if by copying bytes, per C 2018 7.24.2.1 2.) This will of course only reinterpret the low-addressed bytes of the double as a float, which has two problems:
The low-address bytes may not be the ones that contain the most significant bytes of the double.
float and double commonly use different formats, and the difference is not simply that float has fewer bits in the significand (the fraction portion). The exponent field is also a different width and has a different encoding bias. So reinterpreting the double this way generally will not give you a float that has about the same value as a double.
I didn't know how many bytes it would shift but coincidentally i discovered that it shifts by one just like char pointers.
Supporting arithmetic on void * is a GCC extension that is, as far as I know, needless. When offsets are added to or subtracted from void *, GCC does arithmetic as if it were a char *. This appears to be needless because one can do the desired arithmetic simply by using a char * instead of a void *, so the extension does not provide any new function.
Will the accessibility of memory space get changed or just informing the compiler take the variable of mentioned type?
Example:
int main()
{
char a;
a = 123456789;
printf("ans is %d\n",(int)a);
}
Output:
overflow in implicit constant conversion a= 123456789.
ans is 21.
Here I know why it's causing overflow. But I want to know how memory is accessed when an overflow occurs.
This is kind of simple: Since char typically only holds one byte, only a single byte of 123456789 will be copied to a. Exactly how depends on if char is signed or unsigned (it's implementation-specific which one it is). For the exact details see e.g. this integer conversion reference.
What typically happens (I haven't seen any compiler do any different) is that the last byte of the value is copied, unmodified, into a.
For 123456789, if you view the hexadecimal representation of the value it will be 0x75bcd15. Here you can easily see that the last byte is 0x15 which is 21 in decimal.
What happens with the casting to int when you print the value is actually nothing that wouldn't happen anyway... When using variable-argument functions like printf values of a smaller type than int will be promoted to an int. Your printf call is exactly equal to
printf("ans is %d\n",a);
Suppose I define a union like this:
#include <stdio.h>
int main() {
union u {
int i;
float f;
};
union u tst;
tst.f = 23.45;
printf("%d\n", tst.i);
return 0;
}
Can somebody tell me what the memory where tst is stored will look like?
I am trying to understand the output 1102813594 that this program produces.
It depends on the implementation (compiler, OS, etc.) but you can use the debugger to actually see the memory contents if you want.
For example, in my MSVC 2008:
0x00415748 9a 99 bb 41
is the memory contents. Read from LSB on the left side (Intel, little-endian machine), this is 0x41bb999a or indeed 1102813594.
Generally, however, the integer and float are stored in the same bytes. Depending on how you access the union, you get the integer or floating point interpretation of those bytes. The size of the memory space, again, depends on the implementation, although it's usually the largest of its constituents aligned to some fixed boundary.
Why is the value such as it is in your (or mine) case? You should read about floating-point number representation for that (look up ieee 754)
The result is depends on the compiler implementation, But for most x86 compilers, float and int will be the same size. Wikipedia has a pretty good diagram of the layout of a 32 bit float http://en.wikipedia.org/wiki/Single_precision_floating-point_format, that can help to explain 1102813594.
If you print out the int as a hex value, it will be easier to figure out.
printf("%x\n", tst.i);
With a union, both variables are stored starting at the same memory location. A float is stored in an IEEE format (can't remember the standard number, you can look that up[edit: as pointed out by others, IEEE 754]). But, it will be a two's complement normalized (mantissa is always between 0 and 10, exponent can be anything) floating point number.
you are taking the first 4 bytes of that number (again, you can look up what bits go where in the 16 or 32 bits that a float takes up, can't remember). So it basically means nothing and it isn't useful as an int. That is, unless you know why you would want to do something like that, but usually, a float and int combo isn't very useful.
And, no, I don't think it is implementation defined. I believe that the standard dictates what format a float is in.
In union, members will be share the same memory. so that we can get the float value as integer value.
Floating number format will be different from integer storage. so that we can understand the difference using the union.
For Ex:
If I store the 12 integer value in ( 32 bits ). we can get this 12 value as floating point format.
It will stored as signed(1 bit), exponent(8 bits) and significant precision(23 bits).
I wrote a little program that shows what happens when you preserve the bit pattern of a 32-bit float into a 32-bit integer. It gives you the exact same output you are experiencing:
#include <iostream>
int main()
{
float f = 23.45;
int x = *reinterpret_cast<int*>(&f);
std::cout << x; // 1102813594
}
I have the following code:
void main()
{
char tmp[3]= "AB";
short k;
memcpy(&k,tmp,2);
printf("%x\n", k);
}
In ASCII, the hex value of char 'A' is 41 and the hex value of char 'B' is 42. Why is the result of this program 4241? I think the correct result is 4142.
You are apparently running this on a "little-endian" machine, where the least significant byte comes first. See http://en.wikipedia.org/wiki/Endianness.
Your platform stores less significant bytes of a number at smaller memory addresses, and more significant bytes at higher memory addresses. Such platforms are called little-endian platforms.
However, when you print a number the more significant digits are printed first while the less significant digits are printed later (which is how our everyday numeric notation works). For this reason the result looks "reversed" compared to the way it is stored in memory on a little-endian platform.
If you compile and run the same program on a big-endian platform, the output should be 4142 (assuming a platform with 2-byte short).
P.S. One can argue that the "problem" in this case is the "weirdness" of our everyday numerical notation: we write numbers so that the significance of their digits increase in right-to-left direction. This appears to be inconsistent in the context of societies that write and read in left-to-right direction. In other words, it in not the little-endian memory that is reversed. It is the way we write numbers that is reversed.
Your system is little-endian. That means that a short (16-bit integer) is stored with the least significant byte first, followed by the most significant byte.
The same goes for larger integers. The following code would result in "44434241".
void main()
{
char tmp[5]= "ABCD";
int k;
memcpy(&k,tmp,4);
printf("%x\n", k);
}
It's difficult to tell what is being asked here. This question is ambiguous, vague, incomplete, overly broad, or rhetorical and cannot be reasonably answered in its current form. For help clarifying this question so that it can be reopened, visit the help center.
Closed 11 years ago.
Alright actually I've study about how to use looping to make my code more efficient so that I could use a particular block of code that should be repeated without typing it over and over again, and after attempted to use what I've learn so far to program something, I feel it's time for me to proceed to the next chapter to learn on how to use control statement to learn how to instructs the program to make decision.
But the thing is that, before I advance myself to it, I still have a few question that need any expert's help on previous stuff. Actually it's about datatype.
A. Character Type
I extract the following from the book C primer Plus 5th ed:
Somewhat oddly , C treats character
constans as type int rather than
char. For example, on an ASCII system
with a 32-bit int and an 8-bit char
, the code:
char grade = 'B';
represents 'B' as the numerical value
66 stored in a 32-bit unit, grade
winds up with 66 stored ub ab 8-bit
unit. This characteristic of character
constants makes it possible to define
a character constant such as 'FATE',
with four separate 8-bit ASCII codes
stored in a 32-bit unit. However ,
attempting to assign such a character
constant to a char variable results
in only the last 8 bits being used,
so the variable gets the value 'E'.
So the next thing I did after reading this was of course, follow what it mentions, that is I try store the word FATE on a variable with char grade and try to compile and see what it'll be stored using printf(), but instead of getting the character 'E' printed out, what I get is 'F'.
Does this mean there's some mistake in the book? OR is there something I misunderstood?
From the above sentences, there's a line says C treats character constants as type int. So to try it out, I assign a number bigger than 255, (e.x. 356) to the char type.
Since 356 is within the range of 32-bit int (I'm running Windows 7), therefore I expect it would print out 356 when I use the %d specifier.
But instead of printing 356, it gives me 100, which is the last 8-bits value.
Why does this happen? I thought char == int == 32-bits? (Although it does mention before char is only a byte).
B. Int and Floating Type
I understand when a number stores in variable in short type is pass to variadic function or any implicit prototype function, it'll be automatically promoted to int type.
This also happen to floating point type, when a floating-point number with float type is passed, it'll be converted to double type, that is why there's no specifier for the float type but instead there's only %f for double and %Lf for long double.
But why there's a specifier for short type although it is also promoted but not float type? Why don't they just give a specifier for float type with a modifier like %hf or something? Is there anything logical or technical behind this?
A lot of questions in one question... Here are answers to a couple:
This characteristic of character constants makes it possible to define a character constant such as 'FATE' , with four separate 8-bit ASCII codes stored in a 32-bit unit.However , attempting to assign such a character constant to a char variable results in only the last 8 bits being used , so the variable gets the value 'E'.
This is actually implementation defined behavior. So yes, there's a mistake in the book. Many books on C are written with the assumption that the only C compiler in the world is the one the author used when testing the examples.
The compiler the author use treated the characters in 'FATE' as the bytes of an integer with the 'F' being the most significant byte and 'E' being the least significant. Your compiler treats the characters in the literal as bytes of an inteder with 'F' being the least significant byte and 'E' the most significant. For example, The first method is how MSVC treats the value, while MinGW (a GCC compiler targeting Windows) treats the literal in the second way.
As far as there being no format specifier to printf() that expects float, on specifiers that expect double - this is because the values passed to printf() for formatting are part of the variable argument list (the ... in printf()'s prototype). There is not type information about these arguments, so as you mentioned, the compiler must always promote them (from C99 6.5.2.2/6 "Function calls"):
If the expression that denotes the called function has a type that does not include a prototype, the integer promotions are performed on each argument, and arguments that have type float are promoted to double. These are called the default argument promotions.
And C99 6.5.2.2/7 "Function calls"
The ellipsis notation in a function prototype declarator causes argument type conversion to stop after the last declared parameter. The default argument promotions are performed on trailing arguments.
So in effect, it's impossible to pass a float to printf() - it will always be promoted to a double. That's why the format specifiers for floating point values expect a double.
Also due to the automatic promotion that would be applied to short, I'm honestly not sure if the h specifier for formatting a short is strictly necessary (though it is necessary for use with the n specifier if you want to get the count of characters written to the stream placed in a short). It might be in C because it needs to be there to support the n specifier, historical reasons, or something that I'm just not thinking of.
First, a char is by definition exactly 1 byte wide. Then the standard more or less says that the sizes should be:
sizeof(char) <= sizeof(short) <= sizeof(int) <= sizeof(long)
The exact sizes vary (except for char) by system and compiler but on a 32 bit Windows the sizes with GCC and VC are (AFAIK):
sizeof(short) == 2 (byte)
sizeof(int) == sizeof(long) == 4 (byte)
Your observation of 'F' versus 'E' in this case is a typical endianness issue (little vs. big endian, how a "word" is stored in memory).
Now what happens to your value ? You have a variable that is 8 bit wide. You assign a bigger value ('FATE' or 356), but the compiler knows it only is allowed to store 8 bits so it cuts off all the other bits.
To A:
3.) This is due to the different byte orderings of big and little endian CPU achitectures. You get the first byte on a little endian (i.e. x86) and the last byte on a big endian CPU (i.e. PPC). Actually you get always the lowest 8 bit when the conversion fom int to char is done but the characters in the int are stored in reversed order.
7.) a char can only hold 8 bits, so everything else gets truncated in the moment you assign the int to a char variable and can never be restored from the char variable later.
To B:
3.) You might sometimes want to print only the lowest 16 bits of a int variable regardless of what is in the higher half. It is not uncommon to pack multiple integer values in a single variable for certain optimizations. This works well for integer types but makes not much sense for floating point types which don't support bitwise operations directly, which might be the reason why there is no separate type specifier for float in printf.
char is 1 byte long. The bit length of a byte can be 8, 16, 32 bits long. In general purpose computers generally the bitlength of character is 8 bits long. So the maximum number which the character can represent depends on the bitlength of the character. To check the bitlength of character check limits.h header file it is defined as CHAR_BIT in this file.
char x = 'FATE' will depend probably on the byte ordering which the machine/compiler will interpret the 'FATE' . So this depends on the system/compiler. Someone please confirm/correct this.
If your system has 8 bits byte, then, when you do c = 360 only the lower 8 bits of the binary representation of 360 will be stored in the variable, because char data is always allocated 1 byte of storage. So %d will print 100 because the upper bits were lost when you assigned the value in the variable, and what is left is only the lower 8 bits.