{{fbdoc item="title" value="Comparison of FreeBASIC and C integer data types"}}----

This page is a guide for writing ""FreeBASIC"" declarations for C libraries.
It is not a promise that every C type name has one universal ""FreeBASIC""
spelling.

C has two different concerns that are easy to mix up:

	- ABI compatibility: the argument has the same size, signedness, alignment,
	  and calling convention.
	- C spelling compatibility: the generated declaration uses the same C type
	  spelling, which can matter for C++ name mangling, GCC/Clang builtin
	  prototype checks, and compiler diagnostics.

For ordinary ##Extern "C"## calls, ABI compatibility is often enough.  For C++
bindings and compiler builtins, exact C spelling can matter.

The most important rule is that ##[[KeyPgLong|Long]]## in ""FreeBASIC"" is
always 32-bit.  It is not the same thing as C ##long## on all targets.
##[[KeyPgInteger|Integer]]## is pointer-sized: 32-bit on 32-bit targets and
64-bit on 64-bit targets.

{{fbdoc item="section" value="Common C data models"}}

{{table columns="6" cellpadding="1" cells="C data model; Example targets in this tree; C int; C long; C long long; Pointer size; ILP32; DOS, Win32, 32-bit Linux/BSD/Android, Wii, Xbox, WebAssembly/JavaScript; 32 bits; 32 bits; 64 bits; 32 bits; LLP64; Win64, Windows ARM64; 32 bits; 32 bits; 64 bits; 64 bits; LP64; 64-bit Linux/BSD/Android/macOS/Solaris/illumos/Haiku/Cygwin; 32 bits; 64 bits; 64 bits; 64 bits "}}

All targets supported by this tree use a 32-bit C ##int##.  This is a statement
about the targets supported here, not about every possible C implementation.

{{fbdoc item="section" value="FreeBASIC integer sizes"}}

{{table columns="4" cellpadding="1" cells="FreeBASIC type; Signedness; Size; Good ABI match for; Byte; signed; 8 bits; signed char; UByte; unsigned; 8 bits; unsigned char or raw bytes; Short; signed; 16 bits; short; UShort; unsigned; 16 bits; unsigned short; Long; signed; 32 bits; int, int32_t on most supported targets; ULong; unsigned; 32 bits; unsigned int, uint32_t on most supported targets; LongInt; signed; 64 bits; long long; ULongInt; unsigned; 64 bits; unsigned long long; Integer; signed; pointer size; intptr_t or pointer-sized indexes; UInteger; unsigned; pointer size; uintptr_t, size/count values when the target typedef agrees; Any Ptr; pointer; pointer size; void * or opaque handles "}}

The table above is about ABI-sized values.  It is not enough when the exact C
spelling matters.  For example, on LP64 targets C ##long## and C ##long long##
are both 64-bit, but they are still different C types.

{{fbdoc item="section" value="Recommended binding choices"}}

{{table columns="4" cellpadding="1" cells="C type or typedef; Use in FreeBASIC; Why; Notes; signed char; Byte; exact 8-bit signed storage; Plain C char is a different C spelling; unsigned char; UByte; exact 8-bit unsigned storage; Also useful for raw byte buffers; char; ZString Ptr for C strings, otherwise a deliberate Byte/UByte based alias; C char signedness is target dependent; Plain char is distinct from signed char and unsigned char in C++; short; Short; exact 16-bit signed storage; ; unsigned short; UShort; exact 16-bit unsigned storage; ; int; Long; C int is 32-bit on supported targets; ; unsigned int; ULong; C unsigned int is 32-bit on supported targets; ; long; target c_long alias; C long is 32-bit on ILP32/LLP64 and 64-bit on LP64; Do not blindly use FB Long; unsigned long; target c_ulong alias; same data model issue as C long; Do not blindly use FB ULong; long long; LongInt; natural 64-bit signed long long spelling; Not the exact spelling of LP64 C long; unsigned long long; ULongInt; natural 64-bit unsigned long long spelling; Not the exact spelling of LP64 unsigned long; int32_t, uint32_t; crt/stdint.bi typedefs; fixed-width C typedefs are already translated; Use Long/ULong only when the actual header spelling does not matter; int64_t, uint64_t; crt/stdint.bi typedefs; fixed-width 64-bit typedef spelling can differ by target; Do not assume every int64_t is C long long; intptr_t, uintptr_t; crt/stdint.bi typedefs; pointer-sized integer typedefs; Integer/UInteger are the underlying FB-sized types; ptrdiff_t, size_t, ssize_t; crt/stddef.bi typedefs; spelling differs between LP64, LLP64 and some 32-bit targets; Avoid hand-written mappings unless needed; wchar_t, wint_t; crt/stddef.bi typedefs; width and signedness vary by target; Never assume wchar_t is always 16-bit; enum; usually Long for ordinary C enums; ordinary C enum ABI is normally int-sized on these targets; verify packed enums, compiler flags, and C++ scoped enums "}}

For target-specific C ##long##, define a small alias once and use it in the
binding:

{{fbdoc item="ex"}}%%(freebasic)
' C long follows the target C data model.
#if defined( __FB_64BIT__ ) and defined( __FB_UNIX__ )
	type c_long  as integer  alias "long"
	type c_ulong as uinteger alias "long"
#else
	type c_long  as long  alias "long"
	type c_ulong as ulong alias "long"
#endif

extern "C"
	declare function c_function( byval value as c_long ) as c_long
end extern
%%

For standard C typedefs, prefer the translated CRT headers instead of spelling
the mapping by hand:

%%(freebasic)
#include once "crt/stddef.bi"   ' size_t, ptrdiff_t, wchar_t
#include once "crt/stdint.bi"   ' int32_t, uint64_t, intptr_t
%%

{{fbdoc item="section" value="Common mistakes"}}

	- Do not translate C ##long## as ""FreeBASIC"" ##Long## without checking the
	  target data model.
	- Do not translate LP64 C ##long## as ##LongInt## when exact C spelling
	  matters.  The size matches, but the C type is ##long##, not ##long long##.
	- Do not use ##Integer## as a universal replacement for C ##long##.
	  ##Integer## is pointer-sized, while C ##long## is ABI-model-sized.
	- Do not assume ##size_t## is always the same C spelling as
	  ##unsigned long## or ##unsigned long long##.  Use the target typedef.
	- Do not assume plain C ##char## has the same signedness on every target.
	  Use ##signed char## or ##unsigned char## in the C API when signedness
	  matters.
	- Do not assume standard typedefs such as ##time_t##, ##wchar_t##, or
	  ##ssize_t## are the same across all operating systems.

{{fbdoc item="see"}}
	- [[DevBindingCreation|Creating FB bindings for C libraries]] - How to translate C data types to FB
	- [[TblVarTypes|Standard Data Type Limits]]
	- [[KeyPgInteger|Integer]]
	- [[KeyPgLong|Long]]
	- [[KeyPgLongint|LongInt]]
	- [[KeyPgTypeAlias|Type (Alias)]]

{{fbdoc item="back" value="DocToc|Table of Contents"}}
