So I think I'm a bit confused. I'm searching information about the limits of the differents types of integers. I've seen that the limit for unsigned long int is 4294967295 but when I do:
cout << numeric_limits<unsigned long int>::max() << endl;
I'm getting:
18446744073709551615
And if I'm not wrong this number is the limit of unsigned long long, isn'it? So what is happening?
Thank you
I've seen that the limit for unsigned long int is 4294967295
Whoever told you that was wrong.
The limit for unsigned long int will usually be that on systems for which the type is 32-bit.
But yours is evidently 64-bit, so you have a different limit.
this number is the limit of unsigned long long, isn'it?
Again, you're making assumptions about type width.
The width of types varies across compilers/platforms.
If you want to use types with a fixed size, then those do exist.
The standard only defines lower bounds for the limits of integers. For example, the lower bound for the maximum that an unsigned long can represent is 4294967295.
std::numeric_limits<unsigned long>::max() gives the implementation-defined maximum value an unsigned long can represent (i.e. what the current implementation aka compiler/linker/etc actually supports).
This means it is required that
std::numeric_limits<unsigned long>::max() gives a value that is 4294967295 or more. There is nothing preventing it giving a larger result. However, an implementation that gives a smaller result is non-compliant with the standard.
Note that, when moving between compilers, the only guarantee is "4294967295 or more". If one implementation gives a larger value, there is no guarantee that another implementation will.
For the most part, the standard actually says nothing whatsoever about the number of actual bits used to represent the basic integral types, like unsigned long.
The value 18446744073709551615 is consistent with a 64-bit unsigned long, in practice.
Similar stories, albeit with different values, for other integral types (int, char, short, long, etc).
Related
Why do I get two different results? Unsigned long is big enough to handle such number, and it can't be an overflow of some kind, right?
I am deliberately trying to make it show in decimal form, but it just doesn't work.
What could be the reason?
#include <iostream>
using namespace std;
void Print(unsigned long num)
{
cout<<dec<<num<<endl;
}
int main()
{
Print(9110865112);
cout<<dec<<9110865112;
return 0;
}
Edit
It outputs:
520930520
9110865112
unsigned long is not always sufficiently large. With 32 bits it can occupy integers from 0 up to and including 232-1, which is about four billions. 9'110'865'112 is nine billions and would thus not fit into unsigned long.
Try outputting sizeof unsigned long and see what you get.
Also, consider your output: 9110865112 mod 232 is 520930520, which basically proves that unsigned long is 32 bit large on your machine.
The problem is that the numeric literal that you specify is too large to fit in an unsigned long.
When you use the literal directly, the compiler treats it as long long, and chooses the proper overload for operator <<.
To fix this problem, use unsigned long long in the signature of the Print function:
void Print(unsigned long long num)
{
cout<<dec<<num<<endl;
}
Demo.
Because 9,110,865,112 is greater than 32 bits, the method is only accepting 32 of the bits even though you're trying to pass it more.
To fix this, you should use an unsigned long long data type for you num parameter. When you print it directly written as a constant, the code prints out find because the compiler says that constant is an unsigned long long, but when you pass it as an unsigned long, the compiler says that constant should be an unsigned long. Because it's not an unsigned long, it drops some of the bits. (I'm suprised your compiler didn't print out a warning.)
As a reference, an unsigned long can hold values between 0 and 4,294,967,295 (inclusive). Any value great than this should be assigned a larger data type. An unsigned long long can hold values between 0 and 18,446,744,073,709,551,615 (inclusive).
It is worth noting that frequently the data types uint32_t and uint64_t are used in place of unsigned long and unsigned long long respectively. The u denotes that the number is unsigned (if the u is left out, the number is assumed to be signed). The number (64 and 32 in this case) states how many bytes the number should have. And _t at the end just indicates that this is a data type. So (u)int#_t is a common way to write numeric data types; # can be 8, 16, 32, or 64 in standard C++ depending on the number of bits you need.
To summarize: You're throwing a number that's too large at the function. You need to change your function's parameters to support this number:
void Print(uint64_t num){
cout << dec << num << endl;
}
I am transitioning from Java to C++ and have some questions about the long data type. In Java, to hold an integer greater than 232, you would simply write long x;. However, in C++, it seems that long is both a data type and a modifier.
There seems to be several ways to use long:
long x;
long long x;
long int x;
long long int x;
Also, it seems there are things such as:
long double x;
and so on.
What is the difference between all of these various data types, and do they all have the same purpose?
long and long int are identical. So are long long and long long int. In both cases, the int is optional.
As to the difference between the two sets, the C++ standard mandates minimum ranges for each, and that long long is at least as wide as long.
The controlling parts of the standard (C++11, but this has been around for a long time) are, for one, 3.9.1 Fundamental types, section 2 (a later section gives similar rules for the unsigned integral types):
There are five standard signed integer types : signed char, short int, int, long int, and long long int. In this list, each type provides at least as much storage as those preceding it in the list.
There's also a table 9 in 7.1.6.2 Simple type specifiers, which shows the "mappings" of the specifiers to actual types (showing that the int is optional), a section of which is shown below:
Specifier(s) Type
------------- -------------
long long int long long int
long long long long int
long int long int
long long int
Note the distinction there between the specifier and the type. The specifier is how you tell the compiler what the type is but you can use different specifiers to end up at the same type.
Hence long on its own is neither a type nor a modifier as your question posits, it's simply a specifier for the long int type. Ditto for long long being a specifier for the long long int type.
Although the C++ standard itself doesn't specify the minimum ranges of integral types, it does cite C99, in 1.2 Normative references, as applying. Hence the minimal ranges as set out in C99 5.2.4.2.1 Sizes of integer types <limits.h> are applicable.
In terms of long double, that's actually a floating point value rather than an integer. Similarly to the integral types, it's required to have at least as much precision as a double and to provide a superset of values over that type (meaning at least those values, not necessarily more values).
Long and long int are at least 32 bits.
long long and long long int are at least 64 bits. You must be using a c99 compiler or better.
long doubles are a bit odd. Look them up on Wikipedia for details.
long is equivalent to long int, just as short is equivalent to short int. A long int is a signed integral type that is at least 32 bits, while a long long or long long int is a signed integral type is at least 64 bits.
This doesn't necessarily mean that a long long is wider than a long. Many platforms / ABIs use the LP64 model - where long (and pointers) are 64 bits wide. Win64 uses the LLP64, where long is still 32 bits, and long long (and pointers) are 64 bits wide.
There's a good summary of 64-bit data models here.
long double doesn't guarantee much other than it will be at least as wide as a double.
While in Java a long is always 64 bits, in C++ this depends on computer architecture and operating system. For example, a long is 64 bits on Linux and 32 bits on Windows (this was done to keep backwards-compatability, allowing 32-bit programs to compile on 64-bit Windows without any changes). long int is a synonym for long.
Later on, long long was introduced to mean "long (64 bits) on Windows for real this time". long long int is a synonym for this.
It is considered good C++ style to avoid short, int, long etc. and instead use:
std::int8_t # exactly 8 bits
std::int16_t # exactly 16 bits
std::int32_t # exactly 32 bits
std::int64_t # exactly 64 bits
std::size_t # can hold all possible object sizes, used for indexing
You can use these int*_t types by including the <cstdint> header. size_t is in <stdlib.h>.
This looks confusing because you are taking long as a datatype itself.
long is nothing but just the shorthand for long int when you are using it alone.
long is a modifier, you can use it with double also as long double.
long == long int.
Both of them take 4 bytes.
Historically, in early C times, when processors had 8 or 16 bit wordlength,intwas identical to todays short(16 bit). In a certain sense, int is a more abstract data type thanchar,short,longorlong long, as you cannot be sure about the bitwidth.
When definingint n;you could translate this with "give me the best compromise of bitwidth and speed on this machine for n". Maybe in the future you should expect compilers to translateintto be 64 bit. So when you want your variable to have 32 bits and not more, better use an explicitlongas data type.
[Edit: #include <stdint.h> seems to be the proper way to ensure bitwidths using the int##_t types, though it's not yet part of the standard.]
There is no deffirence, (long long x ) is equivalent to (long long int x ), but the second confirms that variable x is integer
I've been programming in C++ for quite a while now and I am pretty familiar with most of the stuff. One thing that I've never understood though is the 'long' data type.
I googled it but I still don't know what it is for. I've found pages that say it is the same size and has the same range as an int. So what would be the point in using it?
I found another stack overflow question regarding this here:
Difference between long and int data types
And it seems that the only difference between the two is that sometimes the size is different on different systems. Does that mean that an application that uses long on a 64bit machine won't work on a 32bit machine? If so then wouldn't it be better to not use them at all?
Also I noticed stuff called "long int" or even "long long"! Is it a data type or a modifier?
It is compiler dependent. My standards-fu is a bit rusty but I believe it is defined as follows:
char <= short <= int <= long <= long long
where:
char >= 8 bits
short >= 16 bits
int >= 16 bits
long >= 32 bits
long long >= 64 bits
Which means that it is perfectly valid to have char = short = int = long = long long = 64bits and in fact compilers of some DSPs are designed that way.
This underscores the importance of actually reading your compiler documentation.
I noticed stuff called "long int" or even "long long"! Is it a data type or a modifier?
long int is the same as long (just as short int is the same as short).
long long is a distinct data type introduced by several compilers and adopted by C++0x.
Note that there is no such thing as long long long:
error: 'long long long' is too long for GCC
From one of the answers in the question you linked:
The long must be at least the same size as an int, and possibly, but not necessarily, longer.
I can't think of a better way to explain it.
long is guaranteed (at least) 32 bits. int is only guaranteed (at least) 16 bits. on 16- and 8-bit systems long provided range at a cost of efficiency.
cheers & hth.,
This is what the C++03 standard says (3.9.1/2) :
There are four signed integer types:
“signed char”, “short int”, “int”, and
“long int.” In this list, each type
provides at least as much storage as
those preceding it in the list.
So : sizeof(char) <= sizeof(short) <= sizeof(int) <= sizeof(long)
This is what the C++0x (3.9.1/2) and C99 (6.2.5/4) standards say :
There are five standard signed integer
types, designated as signed char,
short int, int, long int, and long
long int.
long is synonym of long int
long long doesn't exist in C++03, but will in C++0x.
I googled it but I still don't know
what its for. I've found pages that
say its the same size and has the same
range as an int. So what would be the
point in using it?
I've wondered the same thing. And concluded that long is now useless.
Prior to the rise of 64-bit systems, the de facto standard for C integer types was:
char = (u)int8_t (Note that C predates Unicode.)
short = int16_t
int = intptr_t [until 64-bit], int_fast16_t
long = int32_t [until 64-bit], intmax_t [until 1999]
long long = int64_t or intmax_t
Today, however, long has no consistent semantics.
If you want an integer that is guaranteed to be 32 bit or 64 bit, there are such types, e.g. int64_t. If you really want to ensure your int are of such a size, use these types instead of long, long long, etc. You'll need to include cstdint for these (stdint.h in C).
I've been searching for a while but couldn't find a definite answer to this apparently simple question: what is the default length of an int?
I know that by default, an int is signed. But is it short or long?
According to the "Fundamental data types"table found in the following page, an int is a long int by default (4 bytes).
http://www.cplusplus.com/doc/tutorial/variables/
Is it always true, or does this depend on the OS (32bit/64bit), the compiler or other things?
It depends on the compiler implementor. An int is supposed to be the best "native" length for the platform. Best native here typically refers to whichever size is most handy/efficient/fast for the targeted processor to work with. Often you can expect int to have the same size as the processor's (integer) registers.
As others have pointed out, there are certain relationships about the various integer types' sizes that the compiler must adhere to, so it's the implementor is not free to choose anything. For instance, int can't be larger than long, and so on.
You often talk about programming models in relationship with issues like these, e.g. a compiler can chose to make the various types different sizes depending on the chosen model.
The standard requires only:
a range of a least ±32767 (i.e., at least 16 bits)
int is no shorter than short and no longer than long. It may be equal in size to one of them, or neither.
The exact size of integer types depends on the compiler. The de facto standard is
char is 8 bits
short is 16 bits
int is 16 bits on 16-bit systems, and 32 bits on both 32- and 64-bit systems
long may be either 32 or 64 bits
It depends on the architecture, that is the microprocessor/microcontroller you're compiling the code for (x86, ARM, PIC, Z80, 8051 etc.) and on the compiler, that is how the compiler implements the fundamental/built in data types.
You are guaranteed that a short int is at least 16 bits, and that a long int is at least 32 bits, and that plain int will be no smaller than a short nor larger than a long. But the actual sizes will be decided by the compiler implementor.
The C++ Standard says it like this :
3.9.1, §2 :
There are five signed integer types :
"signed char", "short int", "int",
"long int", and "long long int". In
this list, each type provides at least
as much storage as those preceding it
in the list. Plain ints have the
natural size suggested by the
architecture of the execution
environment (44); the other signed
integer types are provided to meet
special needs.
(44) that is, large enough to contain
any value in the range of INT_MIN and
INT_MAX, as defined in the header
<climits>.
The conclusion : it depends on which architecture you're working on. Any other assumption is false.
$4.4 from "The C++ programming Language" by Bjarne
Like char, each integer type comes in three forms: ‘‘plain’’ int , signed int, and unsigned int . In addition, integers come in three sizes: short int , ‘‘plain’’ int , and long int. A long int can be referred to as plain long . Similarly, short is a synonym for short int , unsigned for unsigned int, and signed for signed int .
The unsigned integer types are ideal for uses that treat storage as a bit array. Using an unsigned instead of an int to gain one more bit to represent positive integers is almost never a good idea. Attempts to ensure that some values are positive by declaring variables unsigned will typically be defeated by the implicit conversion rules (§C.6.1, §C.6.2.1). Unlike plain chars, plain ints are always signed. The signed int types are simply more explicit synonyms for their plain int counterparts.
Section 4.6 of the same book states
Sizes of C++ objects are expressed in terms of multiples of the size of a char , so by definition the size of a char is 1 . The size of an object or type can be obtained using the sizeof operator
(§6.2). This is what is guaranteed
about sizes of fundamental types:
1 <= sizeof(char) <= sizeof(short) <= sizeof(int) <= sizeof(long)
1 <= sizeof(bool) <= sizeof(long)
sizeof(char) <= sizeof(wchar_t) <= sizeof(long)
sizeof(float) <= sizeof(double) <= sizeof(long double)
sizeof(N) <= sizeof(signed N) <= sizeof(unsigned N)
where N can be char , short int, int ,
or long int . In addition, it is
guaranteed that a char has at least 8
bits, a short at least 16 bits, and a
long at least 32 bits. A char can hold
a character of the machine’s character
set.
This clearly indicates that
sizeof(int) is implementation defined
but is guaranteed to be minimum 32bits
C++03 $3.9.1/3
"For each of the signed integer types,
there exists a corresponding (but
different) unsigned integer type:
“unsigned char”, “unsigned short int”,
“unsigned int”, and “unsigned long
int,” each of which occupies the
same amount of storage and has the
same alignment requirements (3.9) as
the corresponding signed integer
type40) ; that is, each signed integer
type has the same object
representation as its corresponding
unsigned integer type.
I'm new to Windows development and I'm pretty confused.
When I compile this code with Visual C++ 2010, I get an error "constant too large." Why do I get this error, and how do I fix it?
Thanks!
int _tmain(int argc, _TCHAR* argv[])
{
unsigned long long foo = 142385141589604466688ULL;
return 0;
}
The digit sequence you're expressing would take about 67 bits -- maybe your "unsigned long long" type takes only (!) 64 bits, your digit sequence won't fit in its, etc, etc.
If you regularly need to deal with integers that won't fit in 64 bits you might want to look at languages that smoothly support them, such as Python (maybe with gmpy;-). Or, give up on language support and go for suitable libraries, such as GMP and MPIR!-)
A long long is 64 bits and thus holds a maximum value of 2^64, which is 9223372036854775807 as a signed value and 18446744073709551615 as an unsigned value. Your value is bigger, hence it's a constant value that's too large.
Pick a different data type to hold your value.
You get the error because your constant is too large.
From Wikipedia:
An unsigned long long's max value is at least 18,446,744,073,709,551,615
Here is the max value and your value:
18,446,744,073,709,551,615 // Max value
142,385,141,589,604,466,688 // Your value
See why your value is too long?
According to http://msdn.microsoft.com/en-us/library/s3f49ktz%28VS.100%29.aspx, the range of unsigned long long is 0 to 18,446,744,073,709,551,615.
142385141589604466688 > 18446744073709551615
You have reached the limit of your hardware to represent integers directly.
It seems that beyond 64 bits (on your hardware) requires the integer to be simulated by software constructs. There are several projects out there that help.
See BigInt
http://sourceforge.net/projects/cpp-bigint/
Note: Others have misconstrued that long long has a limit of 64 bits.
This is not accurate. The only limitation placed by the language are:
(Also Note: Currently C++ does not support long long (But C does) It is an extension by your compiler (coming in the next version of the standard))
sizeof(long) <= sizeof(long long)
sizeof(long long) * CHAR_BITS >= 64 // Not defined explicitly but deducible from
// The values defined in limits.h
For more details See:
What is the difference between an int and a long in C++?