Definition of int64_t
I am new to C/C++, so I have a couple of questions about a basic type:
a) Can you explain to me the difference between int64_t
and long
(long int
)?
In my understanding, both are 64 bit integers. Is there any reason to choose one over the other?
b) I tried to look up the definition of int64_t
on the web, without much success. Is there an authoritative source I need to consult for such questions?
c) For code using int64_t
to compile, I am currently including <iostream>
, which doesn't make much sense to me. Are there other includes that provide a declaration of int64_t
?
a) Can you explain to me the difference between
int64_t
andlong
(long int
)? In my understanding, both are 64 bit integers. Is there any reason to choose one over the other?
The former is a signed integer type with exactly 64 bits. The latter is a signed integer type with at least 32 bits.
b) I tried to look up the definition of
int64_t
on the web, without much success. Is there an authoritative source I need to consult for such questions?
http://cppreference.com covers this here: http://en.cppreference.com/w/cpp/types/integer. The authoritative source, however, is the C++ standard (this particular bit can be found in §18.4 Integer types [cstdint]).
c) For code using
int64_t
to compile, I am including<iostream>
, which doesn't make much sense to me. Are there other includes that provide a declaration ofint64_t
?
It is declared in <cstdint>
or <cinttypes>
(under namespace std
), or in <stdint.h>
or <inttypes.h>
(in the global namespace).
int64_t
is guaranteed by the C99 standard to be exactly 64 bits wide on platforms that implement it, there's no such guarantee for a long
which is at least 32 bits so it could be more.
§7.18.1.3 Exact-width integer types 1 The typedef name intN_t designates a signed integer type with width N , no padding bits, and a two’s complement representation. Thus, int8_t denotes a signed integer type with a width of exactly 8 bits.
int64_t
is typedef
you can find that in <stdint.h>
in C
An int64_t should be 64 bits wide on any platform (hence the name), whereas a long can have different lengths on different platforms. In particular, sizeof(long) is often 4, ie. 32 bits.
My 2 cents, from a current implementation Point of View and for SWIG users on k8 (x86_64) architecture.
Linux
First long long
and long int
are different types
but sizeof(long long) == sizeof(long int) == sizeof(int64_t)
Gcc
First try to find where and how the compiler define int64_t and uint64_t
grepc -rn "typedef.*INT64_TYPE" /lib/gcc
/lib/gcc/x86_64-linux-gnu/9/include/stdint-gcc.h:43:typedef __INT64_TYPE__ int64_t;
/lib/gcc/x86_64-linux-gnu/9/include/stdint-gcc.h:55:typedef __UINT64_TYPE__ uint64_t;
So we need to find this compiler macro definition
gcc -dM -E -x c /dev/null | grep __INT64
#define __INT64_C(c) c ## L
#define __INT64_MAX__ 0x7fffffffffffffffL
#define __INT64_TYPE__ long int
gcc -dM -E -x c++ /dev/null | grep __INT64
#define __INT64_C(c) c ## L
#define __INT64_MAX__ 0x7fffffffffffffffL
#define __INT64_TYPE__ long int
Clang
clang -dM -E -x c++ /dev/null | grep INT64_TYPE
#define __INT64_TYPE__ long int
#define __UINT64_TYPE__ long unsigned int
Clang, GNU compilers:-dM
dumps a list of macros.-E
prints results to stdout instead of a file.-x c
and -x c++
select the programming language when using a file without a filename extension, such as /dev/null
Ref: https://web.archive.org/web/20190803041507/http://nadeausoftware.com/articles/2011/12/c_c_tip_how_list_compiler_predefined_macros
note: for swig user, on Linux x86_64 use -DSWIGWORDSIZE64
MacOS
On Catalina 10.15 IIRC
Clang
clang -dM -E -x c++ /dev/null | grep INT64_TYPE
#define __INT64_TYPE__ long long int
#define __UINT64_TYPE__ long long unsigned int
Clang:-dM
dumps a list of macros.-E
prints results to stdout instead of a file.-x c
and -x c++
select the programming language when using a file without a filename extension, such as /dev/null
Ref: https://web.archive.org/web/20190803041507/http://nadeausoftware.com/articles/2011/12/c_c_tip_how_list_compiler_predefined_macros
note: for swig user, on macOS x86_64 don't use -DSWIGWORDSIZE64
Visual Studio 2019
First
sizeof(long int) == 4
and sizeof(long long) == 8
in stdint.h
we have:
#if _VCRT_COMPILER_PREPROCESSOR
typedef signed char int8_t;
typedef short int16_t;
typedef int int32_t;
typedef long long int64_t;
typedef unsigned char uint8_t;
typedef unsigned short uint16_t;
typedef unsigned int uint32_t;
typedef unsigned long long uint64_t;
note: for swig user, on windows x86_64 don't use -DSWIGWORDSIZE64
SWIG Stuff
First see https://github.com/swig/swig/blob/3a329566f8ae6210a610012ecd60f6455229fe77/Lib/stdint.i#L20-L24 so you can control the typedef using SWIGWORDSIZE64
but...
now the bad: SWIG Java and SWIG CSHARP do not take it into account
So you may want to use
#if defined(SWIGJAVA)
#if defined(SWIGWORDSIZE64)
%define PRIMITIVE_TYPEMAP(NEW_TYPE, TYPE)
%clear NEW_TYPE;
%clear NEW_TYPE *;
%clear NEW_TYPE &;
%clear const NEW_TYPE &;
%apply TYPE { NEW_TYPE };
%apply TYPE * { NEW_TYPE * };
%apply TYPE & { NEW_TYPE & };
%apply const TYPE & { const NEW_TYPE & };
%enddef // PRIMITIVE_TYPEMAP
PRIMITIVE_TYPEMAP(long int, long long);
PRIMITIVE_TYPEMAP(unsigned long int, long long);
#undef PRIMITIVE_TYPEMAP
#endif // defined(SWIGWORDSIZE64)
#endif // defined(SWIGJAVA)
and
#if defined(SWIGCSHARP)
#if defined(SWIGWORDSIZE64)
%define PRIMITIVE_TYPEMAP(NEW_TYPE, TYPE)
%clear NEW_TYPE;
%clear NEW_TYPE *;
%clear NEW_TYPE &;
%clear const NEW_TYPE &;
%apply TYPE { NEW_TYPE };
%apply TYPE * { NEW_TYPE * };
%apply TYPE & { NEW_TYPE & };
%apply const TYPE & { const NEW_TYPE & };
%enddef // PRIMITIVE_TYPEMAP
PRIMITIVE_TYPEMAP(long int, long long);
PRIMITIVE_TYPEMAP(unsigned long int, unsigned long long);
#undef PRIMITIVE_TYPEMAP
#endif // defined(SWIGWORDSIZE64)
#endif // defined(SWIGCSHARP)
So int64_t
aka long int
will be bind to Java/C# long
on Linux...