What is the difference between Usage
#define CONSTANT_1 (256u)
#define CONSTANT_2 (0XFFFFu)
and
#define CONSTANT_1 (256)
#define CONSTANT_2 (0XFFFF)
when do I really need to add u and what problems we get into if not?
I am more interested in the example expressions where one usage can go wrong with other usage.
The trailing u makes the constant have unsigned type. For the examples given, this is probably unnecessary and may have surprising consequences:
#include <stdio.h>
#define CONSTANT_1 (256u)
int main() {
if (CONSTANT_1 > -1) {
printf("expected this\n");
} else {
printf("but got this instead!\n");
}
return 0;
}
The reason for this surprising result is the comparison is performed using unsigned arithmetics, -1 being implicitly converted to unsigned int with value UINT_MAX. Enabling extra warnings will save the day on modern compilers (-Wall -Werror for gcc and clang).
256u has type unsigned int whereas 256 has type int. The other example is more subtle: 0xFFFFu has type unsigned int, and 0xFFFF has type int except on systems where int has just 16 bits where it has type unsigned int.
Some industry standards such as MISRA-C mandate such constant typing, a counterproductive recommendation in my humble opinion.
The u indicates that the decimal constant is unsigned.
Without that, because the value fits in the range of signed integer, it'll be taken as a signed one.
Quoting C11, chapter 6.4.4.1, Integer constants
The type of an integer constant is the first of the corresponding list in which
its value can be represented.
Suffix Decimal Constant Octal or Hexadecimal Constant
---------------------------------------------------------------------------
none int int
long int unsigned int
long long int long int
unsigned long int
long long int
unsigned long long int
u or U unsigned int unsigned int
unsigned long int unsigned long int
unsigned long long int unsigned long long int
Related
Assume the following code:
uint64_t g_global_var;
....
....
void foo(void)
{
uint64_t local_32bit_low = g_global_var & 0xFFFFFFFF;
....
}
With the current toolchain, this code works as expected, local_32bit_low indeed contains the low 32 bits of g_global_var.
I wonder if it is guaranteed by the standard C that this code will always work as expected?
My concern is that the compiler may treat 0xFFFFFFFF as integer value of -1 and when promoting to uint64_t it would become 0xFFFFFFFFFFFFFFFF.
P.S.
I know that to be on the safe side it is better to use 0xFFFFFFFFULL in this case. The point is that I saw it in a legacy code and I wonder if it worth to be fixed or not.
There is no problem. The integer constant 0xFFFFFFFF has the type that is able to store the value as is.
According to the C Standard (6.4.4.1 Integer constants)
5 The type of an integer constant is the first of the corresponding
list in which its value can be represented
So this value is stored as a positive value.
If the type unsigned int is a 32-bit integer type then the constant will have the type unsigned int.
Otherwise it will have one of the types that can store the value.
long int
unsigned long int
long long int
unsigned long long int
Due to the usual arithmetic conversions in the expression
g_global_var & 0xFFFFFFFF;
it is promoted like
0x00000000FFFFFFFF
Pay attention to that in C there is no negative integer constants. For example an expression like
-10
consists of two sub-expressions: the primary expression 10 and the sub-expression with the unary operator - -19 that coincides with the full expression.
0xffffffff is not -1, ever. It may convert to -1 if you cast or coerce (e.g. by assignment) it to a signed 32-bit type, but integer literals in C always have their mathematical value unless they overflow.
For decimal literals, the type is the narrowest signed type that can represent the value. For hex literals, unsigned types are used before going up to the next wider signed type. So, in the common case where int is 32-bit, 0xffffffff would have type unsigned int. If you wrote it as decimal, it would have type long (if long is 64-bit) or long long (if long is only 32-bit).
The type of an unsuffixed hexadecimal or octal constant is the first of the following list in which its value can be represented:
int
unsigned int
long int
unsigned long int
long long int
unsigned long long int
(For unsuffixed decimal constants, remove the unsigned types from the above list.)
The hexadecimal constant 0xFFFFFFFF can definitely be represented by unsigned long int, so its type will be the first of int, unsigned int, long int or unsigned long int that can represent its value.
Note that although 0xFFFFFFFF > 0 always evaluates to 1 (true), it is possible for 0xFFFFFFFF > -1 to evaluate to either 0 (false) or 1 (true) on different implementations. So you need to be careful when comparing integer constants with each other or with other objects of integer type.
Others have answered the question, just a recomendation, next time (if you are under C11) you can check the type of the expression by yourself using _Generic
#include <stdio.h>
#include <stdint.h>
#define print_type(x) _Generic((x), \
int64_t: puts("int64_t"), \
uint64_t: puts("uint64_t"), \
default: puts("unknown") \
)
uint64_t g_global_var;
int main(void)
{
print_type(g_global_var & 0xFFFFFFFF);
return 0;
}
The ouput is
uint64_t
2 Questions
First, while
long long int num = 1000000000000;
works fine
long long int num = 4014109449;
gives
warning: this decimal constant is unsigned only in ISO C90 [enabled by default]
What does it mean ?
Secondly
long long int num = 1000000*1000000;
gives an overflow warning
while
long long int num = 1000000000000;
is ok,even though they are same.How do i get rid of it? Multiplication gives a garbage value
The problem is that the value 4014109449 is an unsigned long int in C90 but a long long int in C99 because it is too large for a 32-bit long int. While 1000000000000 is too large for any 32-bit type, so is automatically a long long int. The warning relates to the fact that the behaviour differs between C90 and C99.
The solution is to force type agreement between the literal and the variable type by using an appropriate type suffix. In this case:
long long num = 4014109449LL ;
or use a type cast:
long long num = (long long)4014109449 ;
Similarly the expression 1000000 * 1000000 is a multiply of two int types and has an int result, but causes an overflow - there is no automatic promotion to a larger type for int expressions. The solution is again to be explicit about the type of the literal:
long long num = 1000000LL * 1000000LL;
or you can also use a type cast on one or both operands.
long long num = (long long)1000000 * 1000000;
In C90, the type of an unsuffixed decimal integer constant (literal) is the first of
int
long int
unsigned long int
that can represent its value without overflow.
In C99 and later, it's the first of
int
long int
long long int
that can represent its value.
The value 4014109449 happens to be representable as a 32-bit unsigned integer, but not as a 32-bit signed integer. Assuming your system has 32-bit longs, that constant's type is unsigned long int in C90, long long int in C99 and C11.
That's what the warning is telling you. The type of the constant changes depending on which version of the C standard your compiler conforms to.
Note that, regardless of its type, the value of 4014109449 will always be correct, and in your declaration:
long long int num = 1000000000000;
that value will always be correctly converted to long long. But it certainly wouldn't hurt (and would silence the warning) to add a LL suffix to make it explicit that you want a value of type long long:
long long int num = 1000000000000LL;
As for this:
long long int num = 1000000*1000000;
assuming you have 32-bit ints, the constant 1000000 is of type int, and the result of multiplying two int values is also of type int. In this case, the multiplication will overflow. Again, you can avoid the problem by ensuring that the constants are of type long long int:
long long int num = 1000000LL * 1000000LL;
(Note that you can use lowercase ll, but it's a bad idea, since it can be difficult to distinguish the letter l from the digit 1.)
If I write this declaration:
unsigned ux = 2147483648;
(231), will the C compiler treat 2147483648 as an unsigned or signed value?
I've heard that constant values are always treated as signed, but I don't think that's always right.
The value of an unsuffixed decimal constant such as 2147483648 depends on the value of the constant, the ranges of the predefined type, and, in some cases on the version of the C standard you're using.
In C89/C90, the type is the first of:
int
long int
unsigned long int
in which it fits.
In C99 and later, it's the first of:
int
long int
long long int
in which it fits.
You didn't tell us what implementation you're using, but if long int is 32 bits on your system, then 2147483648 will be of type unsigned long int if you have a pre-C99 compiler, or (signed) long long int if you have a C99 or later compiler.
But in your particular case:
unsigned ux = 2147483648;
it doesn't matter. If the constant is of type unsigned int, then it's already of the right type, and no conversion is necessary. If it's of type long long int (as it must be in C99 or later, given 32-bit long), then the value must be converted from that type to unsigned. Conversion from a signed type to an unsigned type is well defined.
So if unsigned is wide enough to represent the value 2147483648, then that's the value that will be stored in ux. And if it isn't (if unsigned int is 16 bits, for example), then the conversion will result in 0 being stored in ux.
You can exercise some control over the type of a constant by appending a suffix to it. For example, 2147483648UL is guaranteed to be of some unsigned type (it could be either unsigned int or unsigned long int).
Incidentally, your question's title is currently "About Class Cast.(if I write unsigned ux=2147483648(2 to the 31 st))", but your question has nothing to do with classes (which don't exist in C) or with casts. I'll edit the question.
Greetings!
I was experimenting with C language till I encountered something very strange.
I was not able to explain myself the result shown below.
The Code:
#include <stdio.h>
int main(void)
{
int num = 4294967295U;
printf("%u\n", num);
return 0;
}
The Question:
1.) As you see, I created an int which can hold numbers between -2147483648 to 2147483647.
2.) When I assign the value 4294967295 to this variable, the IDE shows me a warning message during compilation because the variable overflowed.
3.) Due to curiosity I added a U (unsigned) behind the number and when I recompiled it, the compiler did not return any warning message.
4.) I did further experiments by changing the U (unsigned) to L (long) and LL (long long). As expected, the warning message still persist for these two but not after I change it to UL (unsigned Long) and ULL (unsigned long long).
5.) Why is this happening?
The Warning Message :(For steps 2)
warning #2073: Overflow in converting constant expression from 'long long int' to 'int'.
The Warning Message:(For steps 4 LL & L)
warning #2073: Overflow in converting constant expression from 'long long int' to 'long int'.
And last, thanks for reading my question, your teachings and advices are much appreciated.
As per the ISO C99 standard, section 6.4.4.1 (Integer Constants), subsection Semantics, the type of an integer constant is the first type of the following table where the value can be represented:
Octal or Hexadecimal
Suffix Decimal Constant Constant
none int int
long int unsigned int
long long int long int
unsigned long int
long long int
unsigned long long int
u or U unsigned int unsigned int
unsigned long int unsigned long int
unsigned long long int unsigned long long int
l or L long int long int
long long int unsigned long int
long long int
unsigned long long int
both u or U unsigned long int unsigned long int
and l or L unsigned long long int unsigned long long int
ll or LL long long int long long int
unsigned long long int
both u or U unsigned long long int unsigned long long int
and ll or LL
Particular implementations can have extended integer types that follow the same pattern as above.
Perhaps, by default, the compiler assumes you're typing in signed integers. When you give it 4294967295, that number doesn't fit into a 4-byte integer, so it uses an 8-byte integer to store it, instead. Then it has to do a lossy conversion (long long, AKA 8-byte, to long, AKA 4-byte), so it gives you a warning.
However, when you type 4294967295U, it knows you want an unsigned integer. That number fits into a 4-byte unsigned integer, so it has type long int, and no lossy conversion is necessary. (You're not losing data by going from unsigned long int to long int, just mis-representing it.)
Does C treat hexadecimal constants (e.g. 0x23FE) and signed or unsigned int?
The number itself is always interpreted as a non-negative number. Hexadecimal constants don't have a sign or any inherent way to express a negative number. The type of the constant is the first one of these which can represent their value:
int
unsigned int
long int
unsigned long int
long long int
unsigned long long int
It treats them as int literals(basically, as signed int!). To write an unsigned literal just add u at the end:
0x23FEu
According to cppreference, the type of the hexadecimal literal is the first type in the following list in which the value can fit.
int
unsigned int
long int
unsigned long int
long long int(since C99)
unsigned long long int(since C99)
So it depends on how big your number is. If your number is smaller than INT_MAX, then it is of type int. If your number is greater than INT_MAX but smaller than UINT_MAX, it is of type unsigned int, and so forth.
Since 0x23FE is smaller than INT_MAX(which is 0x7FFF or greater), it is of type int.
If you want it to be unsigned, add a u at the end of the number: 0x23FEu.