Search code examples
ccastinghexdword

How to cast hex value to WORD, DWORD or QWORD and store the result in a double variable?


I'm trying to cast a signed hex number to WORD, DWORD and QWORD by this way:

#include <stdio.h>
#include <stdlib.h>
#include <inttypes.h>

int main(void) {

  printf("WORD=%d\n",  (int16_t) strtol("F123", NULL, 16));
  printf("DWORD=%d\n", (int32_t) strtol("FFFFF123", NULL, 16));
  printf("QWORD=%lld\n", (int64_t) strtol("FFFFFFFFFFFFF123", NULL, 16));

  return 0;
}

But it returns the following:

WORD=-3805
DWORD=2147483647
QWORD=2147483647

http://ideone.com/mqjldk

But why the DWORD and QWORD castings are not returning -3805 too?

I mean: 0xFFFFF123 stored in a DWORD would contain -3805 value in decimal, not 2147483647

Expected output:

WORD=-3805
DWORD=-3805
QWORD=-3805

Do you have an bitwise alternative to do it?


Solution

  • 0xFFFFF123 is out of the range of a long int if a long int have 32 bit, so strtol() return LONG_MAX (0x7FFFFFFF = 2147483647 in our case).

    use strtoull() to convert a string to a unsigned integer with at least 64 bits, and allways check for errors before proceed.

    For print a integer with a specified bit size, use something like this:

    printf("foo=%"PRIu32"\n",(uint32_t) foo);
    

    a better way:

    #include <stdio.h>
    #include <stdlib.h>
    #define __STDC_FORMAT_MACROS  //we need that for PRI[u]8/16/32 format strings
    #include <inttypes.h>
    #include <errno.h>
    
    void error_exit(void)
      {
        perror("ups");
        exit(EXIT_FAILURE);
      }
    
    int main(void) 
      {
        unsigned long long temp;
        errno=0;
        temp = strtoull("FFFFF123", NULL, 16);
        if(errno)
          {
            error_exit();
          }
        printf("DWORD=%"PRId32"\n", (int32_t) temp );
        errno=0;
        temp = strtoull("FFFFFFFFFFFFF123", NULL, 16);
        if(errno)
          {
            error_exit();
          }
        printf("QWORD=%"PRId64"\n", (int64_t) temp );
    
        return EXIT_SUCCESS;
      }