Hello, I’m Liang Tang.

This is EasyC++ series 5, talk about C++ long long and __int64.

Click to jump to Github warehouse, have a better reading experience, welcome to the crowd and star~

Long long and __int64

The only 64-bit int mentioned in C++ Primer is long long, but in the actual variety of C++ compilers, there are always two standards for 64-bit ints. One is long long, and another is __int64. Non-mainstream VCS even support _int64.

For the average C++ developer, this doesn’t really matter that much, because most of the time in real development, 32-bit ints will suffice. It is rare to go beyond the int range, but for algorithmic players, it is an issue that must be considered. Because many questions will deliberately make the range large, to test the contestant’s sensitivity to the range of data.

We have a lot to discuss about long long and __int64, let’s take them one at a time.

Issues left over from history

First of all, to talk about the background of this question, why are there two criteria? This is not the C++ standard is not rigorous, or the major compiler is out of order, there is a historical legacy behind the problem.

Long Long was first introduced by C99 standard, however VC6.0 was launched in 1998, before C99 standard. So Microsoft invented a variable called __int64 to represent a 64-bit integer. The first C++ compiler many of you used was VC6.0, so remember to use __int64 instead of long long in VC6.0.

Since VC6.0 made __int64, it was obvious that subsequent versions of Microsoft C++ would have to be compatible with it. So in Windows, the __int64 variable type has been used. Of course, due to the C++ standard update, of course, the latest visual studio already supports long long.

GCC is not windows-based and naturally supports long long. Other ides on the win platform, such as dev C++, CodeBlocks, etc., also support long long because they support __int64 for compatibility with Microsoft systems. So an easy way to tell if the compiler is running on a Windows operating system is to use __int64 if Windows, and long long otherwise.

Cin, cout and scanf, printf selection problem

This problem is also not a problem for C++ developers, there is no need for any choice, no brain cin, cout is done. But it’s still a consideration for algorithmic game players.

Because in algorithm races, especially when there is a large amount of data, the reading and output time can be significant. It looks like the difference between cin Cout and scanf and printf, but the performance difference between the two is quite large.

I have done experiments, and the efficiency of scanf and printf is about ten times that of CIN and cout for the same data. For small amounts of data, of course, it doesn’t make a difference, but for large amounts of data, it makes a big difference. It could lead to the same problem, the same algorithm, and someone else passes, but we run out of time.

There are two main explanations for the performance differences. One explanation is that CIN, in order to mix with scanf without worrying about messy Pointers, has a binding that always keeps stdin in sync. It is this step that consumes a lot of time. Similarly, cout has a similar problem. The second explanation is that cout stores the output in the cache before it is printed out, which also degrades performance by adding an extra step.

There is a solution to the overhead caused by cin synchronizing with stdin, just by adding this line:

std::ios::sync_with_stdio(false);
Copy the code

This line of code means that unsynchronizing the Pointers of cin and cout with stdin and stdout will greatly improve the performance of CIN and cout to the same level as scanf and printf. Of course, it is better to use scanf, printf instead.

There is another problem with using scanf and printf. They are standard INPUT and output methods in C and require identifiers to represent the types of variables. What are identifiers for long long and __int64?

This check is actually know, long long of the identifier is LLD, so we use the scanf read in a long long type number written as:

long long a;
scanf("%lld", &a);
Copy the code

The identifier for __int64 is I64d, note the capital I, not l.

__int64 a;
scanf("%I64d", &a);
Copy the code

But there is a big catch. As mentioned earlier, compilers currently on Windows platforms are already compatible with long long types. However, in visual Studio prior to 2013, we still use %I64d for output because the Msvcrt. DLL library provided by Microsoft only supports %I64d. This essentially shuts down the possibility of using % LLD output. Microsoft fixed this in versions after 2013.

So the easy way to distinguish is to look at the operating system, if the Windows system, then all use __int64 is correct. On Linux or Mac, use long long.

I found the summary table made by Daishen on the Internet, and can also refer to the following table directly:

Variable definitions Output way gcc(mingw32) g++(mingw32) gcc(linux i386) g++(linux i386) MicrosoftVisual c + + 6.0
long long “% LLD” error error correct correct Unable to compile
long long “% I64d” correct correct error error Unable to compile
__int64 “LLD” error error Unable to compile Unable to compile error
__int64 “% I64d” correct correct Unable to compile Unable to compile correct
long long cout The c + + correct The c + + correct Unable to compile
__int64 cout The c + + correct The c + + Unable to compile Unable to compile
long long printint64() correct correct correct correct Unable to compile

Resources: Blog: 64-bit integers in C/C++