Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

A LONGLONG data type in windows api

Tags:

winapi

According to this MSDN page, a data type LONGLONG is defined as below.

#if !defined(_M_IX86)
 typedef __int64 LONGLONG; 
#else
 typedef double LONGLONG;
#endif

And it says LONGLONG is a 64-bit signed integer. But double is a floating-point type, not an integer type. So, do I find a typo? Or am I missing a point?

like image 972
op ol Avatar asked Oct 24 '25 11:10

op ol


2 Answers

This is a documentation bug. It looks to be a lossy conversion from source to documentation1. The actual definition in winnt.h is a fair bit more complex:

//
// __int64 is only supported by 2.0 and later midl.
// __midl is set by the 2.0 midl and not by 1.0 midl.
//

#define _ULONGLONG_
#if (!defined (_MAC) && (!defined(MIDL_PASS) || defined(__midl)) && (!defined(_M_IX86) || (defined(_INTEGRAL_MAX_BITS) && _INTEGRAL_MAX_BITS >= 64)))
typedef __int64 LONGLONG;
typedef unsigned __int64 ULONGLONG;

#define MAXLONGLONG                         (0x7fffffffffffffff)


#else

#if defined(_MAC) && defined(_MAC_INT_64)
typedef __int64 LONGLONG;
typedef unsigned __int64 ULONGLONG;

#define MAXLONGLONG                      (0x7fffffffffffffff)


#else
typedef double LONGLONG;
typedef double ULONGLONG;
#endif //_MAC and int64

#endif

To understand what's going on, let's strip this down by removing everything not immediately relevant.

  • Assume that defined(_MAC) evaluates to 0.
  • Assume that defined(_INTEGRAL_MAX_BITS) && _INTEGRAL_MAX_BITS >= 64 evaluates to 1. That appears to be true even going back as far as Visual C++ 6.0.
  • Strip symbols not relevant here (_ULONGLONG_, ULONGLONG, MAXLONGLONG).
  • Apply indentation without changing any other semantics.

The definition is now a lot easier to parse:

//
// __int64 is only supported by 2.0 and later midl.
// __midl is set by the 2.0 midl and not by 1.0 midl.
//

#if !defined(MIDL_PASS) || defined(__midl)
    typedef __int64 LONGLONG;
#else
    typedef double LONGLONG;
#endif

With that it should be clear that the conditional is a guarding the MIDL compiler (not the C++ compiler). The comment above has rationale, too: Version 1 of the MIDL compiler2 didn't support __int64 as a keyword, but version 2 (and later) do.

Translated into English: If this code isn't parsed by the MIDL compiler, or the MIDL compiler's version is 2 or above, alias LONGLONG with __int64. Otherwise (that is, using the MIDL compiler version 1), pick a double as a best effort.

This is of little practical use today. You can assume that LONGLONG is an alias for __int64, regardless of whether the definition is pulled in by the MIDL or C++ compiler. I wasn't able to find a version history for MIDL.exe, but I assume that version 1 is "ancient".


1 I'm reluctant to accept that having .NET developers write the tooling to generate C documentation from source was a Good Idea™.
2 This refers to the compiler version, not the MIDL language version.

like image 57
IInspectable Avatar answered Oct 28 '25 02:10

IInspectable


With your code snippet, I think it is approach to guarantee that LONGLONG is 64bit under your environment Because double is the only 64bit type which is supported by _M_IX86 in the standard, maybe POSIX. The standard has no __int64 type.

like image 42
999 Avatar answered Oct 28 '25 04:10

999



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!