Data type `long` in C programming - c

What is the difference between
long int numberOfPoints = 131071100; and
long int numberOfPoints = 131071100L;
and is an assignment such as
int numberOfPoints = 131071100L;
legal? And if it is what is the difference between that and the previous two?

The type of an unsuffixed integer constant like 131071100 is the first of int, long int, and long long int in which its value can be represented. The value of 131071100 is always mathematically correct; only its type varies (and since long int is at least 32 bits, it's always either an int or a long int).
With the L suffix, it's of type long int or long long int; again, the value is always correct -- and it happens that 131071100L is always of type long int.
It's perfectly valid to initialize an object of some arithmetic type with an expression of a different numeric type. The value is implicitly converted to the target type. And in this case, since the target type is long int, there is no risk of overflow.
For your particular case, the only difference between
long int numberOfPoints = 131071100;
and
long int numberOfPoints = 131071100L;
is that the latter is slightly more explicit; the meaning is exactly the same.
The L suffix is still needed if the expression is more complicated than a single constant. For example, if you write:
long int foo = 1024 * 1024 * 1024;
then each constant 1024 is of type int -- and so is the entire expression. If int happens to be just 16 bits, then the multiplication will overflow, even though the mathematical result would fit in a long int. (The type of a literal is adjusted depending on its value; the type of a large expression is not.) To avoid that problem, you can write:
long int foo = 1024L * 1024L * 1024L;

(A previous answer here was incorrect and has been amended.)
Per the ANSI C specification (similar language exists in C99 and C++ specifications):
The type of an integer constant is the first of the corresponding list
in which its value can be represented.
Unsuffixed decimal: int, long
int, unsigned long int.
Unsuffixed octal or hexadecimal: int, unsigned
int, long int, unsigned long int.
Suffixed by the letter u or U: unsigned int, unsigned long int.
Suffixed by the letter l or L: long
int, unsigned long int.
Suffixed by both the letters u or U and l or L: unsigned long int.
Therefore, there will not be any difference between the two expressions, since C guarantees that the constant's type will be long enough to hold the value.

Related

Why do we use suffix in c variables?

What is the difference between these two declarations?
long int n=12;
long int n=12l;
int n=12l;
and
How does an unsigned variable store signed values?
unsigned int number=-13;
What is the difference between these declarations?
long int n=12;
An int value 12 is assigned to the long variable n.
long int n=12l;
A long value 12l is assigned to the long variable n.
int n=12l;
A long value 12l is assigned to the int variable n.
How can an unsigned variable allow signed values?
unsigned int number=-13;
Why do you think so?
This question is a duplicate.
Why do we use suffix in c variables?
These suffixes are not in the variables. They are in constants. We use suffixes, sometimes, to control the types of the constants.
long int n = 12;
In this, 12 is a constant of type int. Small decimal numerals with no suffix are int by default. A numeral for an integer too big to represent in int will be long int or long long int, or possibly a compiler-specific wider type.
Since n is declared to be long int, the int 12 will be converted to a long int for the initialization. This conversion will not change the value.
long int n = 12l;
Here, 12l is a constant of type long int. Since it is used to initialize a long int, no conversion is necessary.
int n = 12l;
Again, 12l is a long int. However, since it is used to initialize an int, it will be converted to int. Since int can represent the value 12, this conversion will not change the value. If the constant were too large to represent in an int, then the conversion would change the value, in some implementation-defined way.
As to why we use suffixes sometimes, consider 1 << 31. The 1 is an int, and we shift it left 31 bits. In C implementations common today, an int has 32 bits, and it can represent numbers from −231 to +231−1. However, 1 << 31 would produce 231, which overflows this int range. The C standard does not define the behavior when that overflow occurs.
To avoid this, we might write 1u << 31. Then 1u is an unsigned int, which can represent numbers from 0 to +232−1. Then 231 fits in this, and there is no overflow. Alternately, if we know long int is 64 bits in the C implementation we are using, we might use 1l << 31, depending on our needs. 1 << 31 would overflow, but 1l << 31 would not.
The u suffix makes a decimal constant unsigned int, unsigned long int, or unsigned long long int, as necessary to holds its value (or possibly a wider type supported by the compiler).
The l suffix makes a decimal constant at least long int (skipping int), but the constant will still be long long int if its value is too large for long int.
If an integer constant is written using octal (starts with 0) or hexadecimal (starts with 0x), then it both signed and unsigned types are considered until one is found that can represent its value: int, unsigned int, long int, unsigned long int, long long int, unsigned long long int, and then compiler-specific types.
unsigned int number = -13;
Here 13 is an int constant, and the - is the negation operator, so the result is an int with value −13. (Note there are no negative integer constants in C; you make a negative integer by negating an integer constant.)
Since it is used to initialize an unsigned int, it is converted to unsigned int. When C converts an integer to an unsigned integer type of width M (meaning the type uses M bits to represent values), it is “wrapped” modulo 2M. This means 2M is added to or subtracted from the value until the result is representable in the destination type. For −13 and a 32-bit unsigned int, wrapping −13 modulo 232 produces −13 + 4,294,967,296 = 4,294,967,283.
Wrapping modulo 2M produces the same result as if you wrote the starting number in binary (using two’s complement with more than M bits, if the number is negative) and removed all but the last M bits. For example, −13 in 64-bit two’s complement is 11111111111111111111111111111111111111111111111111111111111100112 = FFFFFFFFFFFFFFF316. The last 32 bits are 111111111111111111111111111100112 = FFFFFFF316. In plain binary (not two’s complement), that is 4,294,967,283.

What is the default data type of number in C?

In C,
unsigned int size = 1024*1024*1024*2;
which results a warning "integer overflow in expression..."
While
unsigned int size = 2147483648;
results no warning?
Is the right value of the first expression is default as int? Where does it mention in C99 spec?
When using a decimal constant without any suffixes the type of the decimal constant is the first that can be represented, in order (the current C standard, 6.4.4 Constants p5):
int
long int
long long int
The type of the first expression is int, since every constant with the value 1024 and 2 can be represented as int. The computation of those constants will be done in type int, and the result will overflow.
Assuming INT_MAX equals 2147483647 and LONG_MAX is greater than 2147483647, the type of the second expression is long int, since this value cannot be represented as int, but can be as long int. If INT_MAX equals LONG_MAX equals 2147483647, then the type is long long int.
unsigned int size = 1024*1024*1024*2;
This expression 1024*1024*1024*2 (in the expression 1024 and 2 are of type signed int) produces result that is of type signed int and this value is too big for signed int . Therefore, you get the warning.
After that signed multiplication it is assigned to unsigned int .

Why is 0 < -0x80000000?

I have below a simple program:
#include <stdio.h>
#define INT32_MIN (-0x80000000)
int main(void)
{
long long bal = 0;
if(bal < INT32_MIN )
{
printf("Failed!!!");
}
else
{
printf("Success!!!");
}
return 0;
}
The condition if(bal < INT32_MIN ) is always true. How is it possible?
It works fine if I change the macro to:
#define INT32_MIN (-2147483648L)
Can anyone point out the issue?
This is quite subtle.
Every integer literal in your program has a type. Which type it has is regulated by a table in 6.4.4.1:
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
If a literal number can't fit inside the default int type, it will attempt the next larger type as indicated in the above table. So for regular decimal integer literals it goes like:
Try int
If it can't fit, try long
If it can't fit, try long long.
Hex literals behave differently though! If the literal can't fit inside a signed type like int, it will first try unsigned int before moving on to trying larger types. See the difference in the above table.
So on a 32 bit system, your literal 0x80000000 is of type unsigned int.
This means that you can apply the unary - operator on the literal without invoking implementation-defined behavior, as you otherwise would when overflowing a signed integer. Instead, you will get the value 0x80000000, a positive value.
bal < INT32_MIN invokes the usual arithmetic conversions and the result of the expression 0x80000000 is promoted from unsigned int to long long. The value 0x80000000 is preserved and 0 is less than 0x80000000, hence the result.
When you replace the literal with 2147483648L you use decimal notation and therefore the compiler doesn't pick unsigned int, but rather tries to fit it inside a long. Also the L suffix says that you want a long if possible. The L suffix actually has similar rules if you continue to read the mentioned table in 6.4.4.1: if the number doesn't fit inside the requested long, which it doesn't in the 32 bit case, the compiler will give you a long long where it will fit just fine.
0x80000000 is an unsigned literal with value 2147483648.
Applying the unary minus on this still gives you an unsigned type with a non-zero value. (In fact, for a non-zero value x, the value you end up with is UINT_MAX - x + 1.)
This integer literal 0x80000000 has type unsigned int.
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.
And this integer constant can be represented by the type of unsigned int.
So this expression
-0x80000000 has the same unsigned int type. Moreover it has the same value
0x80000000 in the two's complement representation that calculates the following way
-0x80000000 = ~0x80000000 + 1 => 0x7FFFFFFF + 1 => 0x80000000
This has a side effect if to write for example
int x = INT_MIN;
x = abs( x );
The result will be again INT_MIN.
Thus in in this condition
bal < INT32_MIN
there is compared 0 with unsigned value 0x80000000 converted to type long long int according to the rules of the usual arithmetic conversions.
It is evident that 0 is less than 0x80000000.
The numeric constant 0x80000000 is of type unsigned int. If we take -0x80000000 and do 2s compliment math on it, we get this:
~0x80000000 = 0x7FFFFFFF
0x7FFFFFFF + 1 = 0x80000000
So -0x80000000 == 0x80000000. And comparing (0 < 0x80000000) (since 0x80000000 is unsigned) is true.
A point of confusion occurs in thinking the - is part of the numeric constant.
In the below code 0x80000000 is the numeric constant. Its type is determine only on that. The - is applied afterward and does not change the type.
#define INT32_MIN (-0x80000000)
long long bal = 0;
if (bal < INT32_MIN )
Raw unadorned numeric constants are positive.
If it is decimal, then the type assigned is first type that will hold it: int, long, long long.
If the constant is octal or hexadecimal, it gets the first type that holds it: int, unsigned, long, unsigned long, long long, unsigned long long.
0x80000000, on OP's system gets the type of unsigned or unsigned long. Either way, it is some unsigned type.
-0x80000000 is also some non-zero value and being some unsigned type, it is greater than 0. When code compares that to a long long, the values are not changed on the 2 sides of the compare, so 0 < INT32_MIN is true.
An alternate definition avoids this curious behavior
#define INT32_MIN (-2147483647 - 1)
Let us walk in fantasy land for a while where int and unsigned are 48-bit.
Then 0x80000000 fits in int and so is the type int. -0x80000000 is then a negative number and the result of the print out is different.
[Back to real-word]
Since 0x80000000 fits in some unsigned type before a signed type as it is just larger than some_signed_MAX yet within some_unsigned_MAX, it is some unsigned type.
C has a rule that the integer literal may be signed or unsigned depends on whether it fits in signed or unsigned (integer promotion). On a 32-bit machine the literal 0x80000000 will be unsigned. 2's complement of -0x80000000 is 0x80000000 on a 32-bit machine. Therefore, the comparison bal < INT32_MIN is between signed and unsigned and before comparison as per the C rule unsigned int will be converted to long long.
C11: 6.3.1.8/1:
[...] Otherwise, if the type of the operand with signed integer type can represent all of the values of the type of the operand with unsigned integer type, then the operand with unsigned integer type is converted to the type of the operand with signed integer type.
Therefore, bal < INT32_MIN is always true.

long long int initialization warnings

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.)

Type of constant in "unsigned ux = 2147483648;"

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.

Resources