I wanna print the value of b[FFFC] like bel开发者_StackOverflowow,
short var = 0xFFFC;
printf("%d\n", b[var]);
But it actually print the value of b[FFFF FFFC].
Why does it happen ?
My computer is operated by Windows XP in 32-bit architecture.
short
is a signed type. It's 16 bits on your implementation. 0xFFFC represents the integer constant 65,532, but when converted to a 16 bit signed value, this is resulting in -4.
So, your line short var = 0xFFFC;
sets var to -4 (on your implementation).
0xFFFFFFFC is a 32 bit representation of -4. All that's happening is that your value is being converted from one type to a larger type, in order to use it as an array index. It retains its value, which is -4.
If you actually want to access the 65,533rd element of your array, then you should either:
- use a larger type for
var
.int
will suffice on 32 bit Windows, but in generalsize_t
is an unsigned type which is guaranteed big enough for non-negative array indexes. - use an
unsigned short
, which just gives you enough room for this example, but will go wrong if you want to get another 4 steps forward.
In current compilers we can't use short
(16 bit) if write short
use 32 bit .
for example i compile same code with gcc4 in Ubuntu Linux 32 bit :
int main(int argc, char** argv)
{
short var = 0xFFFC;
printf("%x\n", var);
printf("%d\n", var);
return (EXIT_SUCCESS);
}
and output is :
fffffffc
-4
you can see cast short to 32bit normal and use sign extension in 2's complement
As a refresher on the C's data types available, have a look here. There is a rule, and that concerns the usage of C, some datatypes are promoted to their integral type, for instance
char ch = '2'; int j = ch + 1;
Now look at the RHS (Right Hand Side) of the expression and notice that the ch
will automatically get promoted as an int in order to produce the desired results on the LHS (LHS) of the expression. What would the value of j
be? The ASCII code for '2' is 50 decimal or 0x32 hexadecimal, add 1 on to it and the value of j
would be 51 decimal or 0x33 hexadecimal.
It is important to understand that rule and that explains why a data type would be 'promoted' to another data type.
What is the b
? That is an array I presume that has 655532 elements correct?
Anyway, using a format specifier %d
is for of type int, the value got promoted to an int, firstly, and secondly the array subscript is of type int
, hence the usage of the short var
got promoted and since the data size of an int is 4 bytes, it got promoted and hence you are seeing the rest of the value 0xFFFF 0xFFFC.
This is where the usage of casting comes in, to tell the compiler to cast a data type to another which explains in conjunction to Gregory Pakosz's answer above.
Hope this helps, Best regards, Tom.
use %hx or %hd instead to indicate that you have a short variable, e.g:
printf("short hex: %hx\n", var); /* tell printf that var is short and print out as hex */
EDIT: Uups, I got the question wrong. It was not about printf() as I thought. So this answer might be a little bit OT.
New: Because you are using var as an index to an array you should declare it as unsigned short (instead of short):
unsigned short var = 0xFFFC;
printf("%d\n", b[var]);
The 'short var' could be interpreted as a negative number.
To be more precise:
You are "underflowing" into the negative value range: Values in the range from 0x0000 upto 0x7FFF will be OK. But values from 0x8000 upto 0xFFFF will be negative.
Here are some examples of var used as an index to array b[]:
short var=0x0000;; // leads to b[0] => OK
short var=0x0001; // leads to b[1] => OK
short var=0x7FFF; // leads to b[32767] => OK
short var=0x8000; // leads to b[-32768] => Wrong
short var=0xFFFC; // leads to b[-4] => Wrong
short var=32767; // leads to the same as b[0x7FFF] => OK
short var=32768; // compile warning or error => overflow into 32bit range
You were expecting to store JUST a 16bit variable in a 32bit-aligned memory... you see, each memory address holds a whole 32bit word (hardware).
The extra FFFF comes from the fact that short is a signed value, and when assigned to int (at the printf call), it got signed-extended. When extending two-complements from 16 to 32bit, the extension is done by replicating the last N bit to all other M-N on it's left. Of course, you did not intend that.
So, in this case, you're interested in absolute array positions, so you should declare your indexer as unsigned.
In the subject of your question you have already guessed what is happening here: yes, a value of type short
is "automatically extended" to a value of type int
. This process is called integral promotion. That's how it always works in C language: every time you use an integral value smaller than int
that value is always implicitly promoted to a value of type int
(unsigned values can be promoted to unsigned int
). The value itself does not change, of course, only the type of the value is changed. In your above example the 16-bit short
value represented by pattern 0xFFFC
is the same as 32-bit int
value represented by pattern 0xFFFFFFFC
, which is -4
in decimals. This, BTW, makes the rest of your question sound rather strange: promotion or not, your code is trying to access b[-4]
. The promotion to int
doesn't change anything.
精彩评论