Why do we use suffix in c variables? - c

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.

Related

Safe low 32 bits masking of uint64_t

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

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.

Data type `long` in C programming

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.

Is the integer constant's default type signed or unsigned?

Is the integer constant's default type signed or unsigned? such as 0x80000000, how can I to decide to use it as a signed integer constant or unsigned integer constant without any suffix?
If it is a signed integer constant, how to explain following case?
printf("0x80000000>>3 : %x\n", 0x80000000>>3);
output:
0x80000000>>3 : 10000000
The below case can indicate my platform uses arithmetic bitwise shift, not logic bitwise shift:
int n = 0x80000000;
printf("n>>3: %x\n", n>>3);
output:
n>>3: f0000000
C has different rules for decimal, octal and hexadecimal constants.
For decimal, it is the first type the value can fit in: int, long, long long
For hexadecimal, it is the first type the value can fit in: int, unsigned int, long, unsigned long, long long, unsigned long long
For example on a system with 32-bit int and unsigned int: 0x80000000 is unsigned int.
Note that for decimal constants, C90 had different rules (but rules didn't change for hexadecimal constants).
It is signed if it fits in a signed integer. To make it unsigned, append a u suffix, e.g. 1234u.
You can convert a signed value to unsigned by assigning it to an unsigned variable.
unsigned int i = 1234u; // no conversion needed
unsigned int i = 1234; // signed value 1234 now converted to unsigned
For 0x80000000, it will be unsigned if ints are 32 bits on your platform, since it doesn't fit into a signed int.
Another thing to watch out for, though, is that the behaviour of right-shift is platform-dependent. On some platforms it's sign-preserving (arithmetic) and on some platforms it's a simple bitwise shift (logical).

Resources