Cheeso
Cheeso

Reputation: 192597

No-overflow cast on x64

I have an existing C codebase that works on x86.

I'm now compiling it for x64.

What I'd like to do is cast a size_t to a DWORD, and throw an exception if there's a loss of data.

Q: Is there an idiom for this?


Here's why I'm doing this:

A bunch of Windows APIs accept DWORDs as arguments, and the code currently assumes sizeof(DWORD)==sizeof(size_t). That assumption holds for x86, but not for x64. So when compiling for x64, passing size_t in place of a DWORD argument, generates a compile-time warning.

In virtually all of these cases the actual size is not going to exceed 2^32. But I want to code it defensively and explicitly.

This is my first x64 project, so... be gentle.

Upvotes: 1

Views: 191

Answers (3)

Carey Gregory
Carey Gregory

Reputation: 6846

#define size_t_to_DWORD(st,dw)  if ((DWORD)(st) != st)  RaiseException(exLossOfData, 0, 0, NULL); else dw = (DWORD)(st)

size_t  st;
DWORD   dw;
st = 0xffffffff;
size_t_to_DWORD(st,dw);  // this succeeds
st = 0xffffffff1;
size_t_to_DWORD(st,dw);  // this throws

EDIT:

Or better yet, do this so you can use it in an expression:

DWORD MyRaiseException()
{
    RaiseException(1, 0, 0, NULL);
    return 0;
}


#define size_t_to_DWORD(st)  (DWORD)(st) != (st) ? MyRaiseException() : (DWORD)(st)


void main(void)
{
    size_t  st;
    DWORD   dw;
    st = 0xffffffff1;
    dw = size_t_to_DWORD(st);
    printf("%u %u\n", st, dw);
}

Upvotes: 0

Cheeso
Cheeso

Reputation: 192597

I just defined a function to perform the cast.

I included an assert-like behavior to insure I'm not silently rubbishing pointers.

DWORD ConvertSizeTo32bits(size_t sz, char *file, int line) 
{
    if (!(0 <= sz && sz <= INT32_MAX)) {
        EmitLogMessage("Invalid Pointer size: %d file(%s) line(%d)",
                       sz, file, line);

        ExitProcess( 0 );  
    }
    return (DWORD) sz;
}

Upvotes: 0

Related Questions