while exploring linux code, came across many definition like below. If ULL is unsigned long long, why it has negative value -11? What the value of below macro?
#define BTRFS_FREE_SPACE_OBJECTID -11ULL
-11ULL is the same as - (11ULL). 11ULL is an unsigned long long with value 11. If you read up how arithmetic operations on unsigned types work, if the mathematical result does not fit into the range, then the largest value + 1 is added or subtracted repeatedly.
The mathematical result -11 doesn't fit, so the largest unsigned long long + 1 is added, and -11ULL gives ten less than the largest possible unsigned long long value. A huge positive number, not negative.
unsigned int a=-1;
is the same as:
unsigned int a=0xffffffff;
Related
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.
I found this code in an algorithm I need to update:
if (value > (unsigned long long) LONG_MAX)
EDIT: value is the result of a division of two uint64_t numbers.
I understand that (unsigned long long) LONG_MAX is a VERY big number:
#include "stdio.h"
#include "limits.h"
int main() {
unsigned long long ull = (unsigned long long) LONG_MAX;
printf("%lu",ull);
return 0;
}
prints 9223372036854775807
So what I am comparing here? In what case this if statement will evaluate to true?
A float or double can be larger than that. Appendix Ep5 of the C standard states that either type must be able to hold a value at least as large as 1E37 which is a larger value than LONG_MAX which must be at least 2147483647:
The values given in the following list shall be replaced by
implementation-defined constant expressions with values that are
greater than or equal to those shown:
#define DBL_MAX 1E+37
#define FLT_MAX 1E+37
#define LDBL_MAX 1E+37
So if value is either of those types, it could evaluate to true.
EDIT:
Since value is a uint64_t, whose max value is 18446744073709551615, this can also be larger than LONG_MAX.
how can something be bigger than (unsigned long long) > LONG_MAX?
Easily. LONG MAX is the maximum value that can be represented as a long int. Converting that to unsigned long long does not change its value, only its data type. The maximum value that can be represented as an unsigned long int is larger on every C implementation you're likely to meet. The maximum value of long long int is larger on some, and the maximum value of unsigned long long int is, again, larger on every C implementation you're likely to meet (much larger on some).
However, this ...
unsigned long long ull = (unsigned long long) LONG_MAX;
printf("%lu",ull);
... is not a conforming way to investigate the value in question because %lu is a formatting directive for type unsigned long, not unsigned long long. The printf call presented therefore has undefined behavior.
I found this code in an algorithm I need to update:
if (value > (unsigned long long) LONG_MAX)
EDIT: value is the result of a division of two uint64_t numbers.
[...]
In what case this if statement will
evaluate to true?
Supposing that value has type uint64_t, which is probably the same as unsigned long long in your implementation, the condition in that if statement will evaluate to true at least when the most-significant bit of value is set. If your long int is only 32 bits wide, however, then the condition will evaluate to true much more widely than that, because there are many 64-bit integers that are larger than the largest value representable as a signed 32-bit integer.
I would be inclined to guess that the code was indeed written under the assumption that long int is 32 bits wide, so that the if statement asks a very natural question: "can the result of the previous uint64_t division be represented as a long?" In fact, that's what the if statement is evaluating in any case, but it makes more sense if long is only 32 bits wide, which is typical of 32-bit computers and standard on both 32- and 64-bit Windows.
LONG_MAX is maximum value for a signed long. By standard it should be >= +2147483647 (fits in 32 bit signed)
There's also ULLONG_MAX for unsigned long long, which is currently most often 18446744073709551615. The standard mandates that to be >= than 9223372036854775807
Program:
#include<stdio.h>
int main()
{
unsigned long int i=1902;
int j=0;
while(j<10)
{
i=i*10;
printf("\n%lu",i);
j++;
}
}
Why am I getting correct results only upto 5 iterations? Please help me to get the correct answer for all iterations. Seeing the range, I changed my int to unsigned long int but still I'm unable to correct the error.
My guess is that you're on a 32-bit system, or using the Microsoft Visual Studio compiler. I guess that because it seems that unsigned long is 32 bits, which means the maximum value it can be is a little over 4 billion.
If you want a 64-bit value then you need to use unsigned long long, which is 64 bits on just about all PC-like systems.
Because at that point the value is out of the range that a unsigned long int can represent, that goes from 0 to 4,294,967,295.
unsigned long int is 4 bytes in almost every C Compiler.
here i is initialized with 1902.
You are multiplying the value of i by 10 at each iteration.
The range of signed long int is from -2,147,483,648 to 2,147,483,647.
By making the variable unsigned you can only double the range of positive integers, ie, from 0 to 4,294,967,295.
The value in variable i crosses maximum range of unsigned integer after 6 iterations. Hence the overflow and negative numbers displayed.
If you want to represent larger numbers use long long int whose size is 64 bits and the range is from −9223372036854775807 to 9223372036854775807.
As we know that 4294967295 is the largest number in unsigned int if I multiply this number by itself then how to display it? I have tried:
long unsigned int NUMBER = 4294967295 * 4294967295;
but still getting 1 as answer.
You are getting an overflow. Consider the muplication in hexadecimal:
0xffffffff * 0xffffffff == 0xfffffffe00000001
^^^^^^^^
only the last 32 bits are returned
The solution is to use a larger type such as long long unsigned:
long long unsigned int NUMBER = 4294967295ULL * 4294967295ULL;
The suffix ULL means unsigned long long.
See it working online: ideone
The multiplication overflows.
#include <stdio.h>
int main()
{
unsigned int a = 4294967295;
unsigned int b = 4294967295;
// force to perform multiplication based on larger type than unsigned int
unsigned long long NUMBER = (unsigned long long)a * b;
printf("%llu\n", NUMBER);
}
You state in your question that you know max int is equal to 4294967295. That means that you can't store a number larger than that if you are using unsigned int.
C longs store up to 18,446,744,073,709,551,615 when unsigned on a 64 bit unix system [source] so you need only suffix your numbers with UL : 4294967295UL
If you aren't using a 64-bit unix system then you should use long long unsigned int and suffix with LL
Yes, it's an overflow. If you are using c, there isn't any easy way to do such big number multiply as i knew. Maybe you need write one by yourself. In fact some language support such features originally.
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.