strlen
The return type of string length functions like strlen
and wcslen
is a size_t
. Since we will never have null terminated strings with more than 2,147,483,647 characters, simply use a cast like so:
int length = (int)wcslen(str); //(int) cast for 64 bit compilers
fread and fwrite
The return type of fread
and fwrite
is a size_t
. Design your calls to fread
and fwrite
so that the count argument is never > 2,147,483,648 and use an int cast on the return type like so:
int count = ...; some number <= 2,147,483,648
if ( count != (int)fread( buffer, size, count, fp ) )
{
//fread failed
//handle file reading error
}
or
int count = ...; some number <= 2,147,483,648
if ( count != (int)fwrite( buffer, size, count, fp ) )
{
//fwrite failed
//handle file writing error
}
If you are compelled to write 9,223,372,036,854,775,808 bytes in a single call to fwrite
, you can do so with:
size_t size = 9223372036854775808;
void* buffer = ...;
FILE* fp = ...;
if ( 1 != fwrite( buffer, size, 1, fp ) )
{
//failed to write 9223 terrabytes in a single call to fwrite - duh
//printf("You're a looser\n");
}
Sort functions that compare pointers
Use INT_PTR
to store the difference between two pointers.
//Sort functions have to return 32 bit ints
static int compar( const void** a, const void** b )
{
//pointer differences have to be INT_PTR (64 bit int on x64)
INT_PTR i = ((const CTheRealType**)b)->pRhinoObject - ((const CTheRealType**)a)->pRhinoObject
//Expect i to be > MAX_INT, so do something like this
return ( (i<0) ? -1 : ( (i>0) ? 1 : 0 );
}
size_t
The type size_t
is 64 bits on a 64-bit compiler. See the strlen
and fread
sections above for examples on dealing with this.
Formatted printing
You really need to pay attention to the size of your integer arguments to formatted printing strings.
int i = ...;
size_t sz = ...;
void* ptr = ...;
INT_PTR ip = ...;
hyper h = ...;
__int64 i64 = ...;
RhinoApp().Print("i = %d sz = %Id ptr = %I08X ip = %Id h = %I64d i64 = %I64d\n",
i,sz,ptr,ip,h,i64);
Windows SendMessage
If you cast the WPARAM
and LPARAM
arguments as (WPARAM
) and (LPARAM
), and put the return value in an LRESULT
, everything works perfectly for both the 32- and 64-bit compilers. Since the value of smresult
can be an int
, pointer
, handle
, whatever, cast smresult
as shown below.
LRESULT smresult = SendMessage((UNIT)id, (WPARAM)>, (LPARAM)sText);
int rc = (int)smresult ; //In this case, I the rest of the code want
HWND hwnd = (HWND)smresult;
char** ptr = (char**)smresult;
Windows SetWindowLong and GetWindowLong
Replace every single instance of Windows calls that pass pointers as mystery meat with the Ptr
versions.
//BAD //GOOD
SetWindowLong -> SetWindowLongPtr
GetWindowLong -> GetWindowLongPtr
If you do this, then your code will work perfectly and compile cleanly on both 32- and 64-bit platforms.
The Ptr
part of the function names is misleading. The Ptr
versions work when the return value or last argument has any type.
Bad:
SetWindowLong( *pDockFrame, GWL_USERDATA, (LONG)this);
WNDPROC wp = (WNDPROC)::GetWindowLong( *pDockFrame, GWL_WNDPROC);
DWORD dwStyle = ::GetWindowLong( pMsg->hwnd, GWL_STYLE)
Good:
SetWindowLongPtr( hwnd, id, (LONG_PTR)this);
WNDPROC wp = (WNDPROC)::GetWindowLongPtr( *pDockFrame, GWL_WNDPROC);
DWORD dwStyle = (DWORD)::GetWindowLongPtr( pMsg->hwnd, GWL_STYLE)
Timers
The value returned by Windows ::SetTimer()
needs to be saved in a UINT_PTR
.