Is there a way to Postfix a letter to a numeral, like in the case of a long integer: 2344532L, but for indicating a byte sized numeral?
Byte and double byte numerals
What exactly are you trying to achieve?
Is there anything wrong with
"unsigned char x = 255;" ?
Do you have a code sample to show what is your intention?
Yes.
For example, If:
#include <stdint.h>
int main()
{
uint8_t var = 0xFF;
uint16_t var2 = var<<8;
return 0;
}
Checking with the debugger the value of var2 after executing its initialization is 0xFF00, which makes me deduce that the compiler transformed var to a uint16_t or bigger when the bit shift happens.
Yes.
For example, If:
#include <stdint.h> int main() { uint8_t var = 0xFF; uint16_t var2 = var<<8; return 0; }
Checking with the debugger the value of var2 after executing its initialization is 0xFF00, which makes me deduce that the compiler transformed var to a uint16_t or bigger when the bit shift happens.
The value would be expected to be 0XFF00 since it was a 16-bit sized variable that would have held 0x00FF had you not applied the bitshift.
Yes.
For example, If:Checking with the debugger the value of var2 after executing its initialization is 0xFF00, which makes me deduce that the compiler transformed var to a uint16_t or bigger when the bit shift happens.#include <stdint.h> int main() { uint8_t var = 0xFF; uint16_t var2 = var<<8; return 0; }
`0xFF' has type int. Then you assign it to `var', which gives `var' the value you expect. So by the time you evaluate `var<<8' it doesn't matter what type the constant had. The reason why you get `0xFF00' instead of `0x0000' as a result can be found in the integer promotion rules. Here's the first match I got in Google: https://www.securecoding.cert.org/confluence/display/seccode/INT02-C.+Understand+integer+conversion+rules
When asking questions like that, it is often better to go directly to the standard rather than to people's interpretation of the standard. You can reference the draft version of the standard that was approved. There are only minor differences between it and the final approved version, like the page headings and the front page.
Take a look at the language grammar that handles integer constants (6.4.4.1).
The only allowed suffix in C are:
u or U - meaning unsigned
l or L - meaning "long", typically a 32-bit number
ll or LL - meaning "long long", typically a 64-bit number.
If you don't have a suffix and the number is small enough to fit inside an int, the numeric constant is an int. If you assign it to a char (which the uint8_t type is under the hood), the value is automatically and silently truncated.
The conversion and promotion rules can lead to lots of fun conditions, several of them are documented in the standard itself.
If you are using uint8_t you can get several interesting effects. Consider:
uint8_t a, b;
/* ... */
uint8_t c = a + b;
According to the arithmetic rules, the values for a and b are both promoted to unsigned integers before the addition takes place, then the result is silently truncated back to an 8-bit value. This can be important for large values of a and b since it may not overflow as you expected.
Not understanding the conversion rules can lead to all kinds of subtle and potentially unexpected (e.g. buggy) behavior.
Edit: Note that C++ has similar but slightly different conversion rules. Any time you play fast-and-loose with types and conversions the rules for automatic conversions and promotions can cause unexpected bugs. As another prime example, mixing 32-bit enum values with 32-bit numeric constants can lead to some unexpected trips into 64-bit land that will silently have radically different results on different compilers.
This is what i get with VS13:
uint8_t var = 0xFF;
00346602 mov byte ptr [ebp-51h],0FFh
uint16_t var2 = var << 8;
00346606 movzx eax,byte ptr [ebp-51h]
0034660A shl eax,8
0034660D mov word ptr [ebp-60h],ax
When you load the value from var into the register, it doesn't care how large the variable was, the value from it now resides in a 32/64 bit register. When it does the shift, it's doing it in a 32/64 bit context. Storing it into var2 just means it's going to take the bottom 16bits, truncating if necessary.
This is what i get with VS13:
uint8_t var = 0xFF; 00346602 mov byte ptr [ebp-51h],0FFh uint16_t var2 = var << 8; 00346606 movzx eax,byte ptr [ebp-51h] 0034660A shl eax,8 0034660D mov word ptr [ebp-60h],ax
When you load the value from var into the register, it doesn't care how large the variable was, the value from it now resides in a 32/64 bit register. When it does the shift, it's doing it in a 32/64 bit context. Storing it into var2 just means it's going to take the bottom 16bits, truncating if necessary.
I would understand it in 32 bit machines, word is 16 bits, so the last assembly statement assigns the first 16 bits of the 32 bit register eax to var2(hence it uses ax.)
But in 64 bit machines, is eax 64 bits and ax 16bits?
But in 64 bit machines, is eax 64 bits and ax 16bits?
Since the 80386, eax is always a 32-bit register, whose lower 16 bits form ax. In AMD64-compatible machines, rax is a 64-bit register whose lower 32 bits form eax.
But your question was about the C language, so I don't know what we are doing talking about processor registers.