Converting an unsigned int to to unsigned long long (64 bit)

This is a discussion on Converting an unsigned int to to unsigned long long (64 bit) within the C Programming forums, part of the General Programming Boards category; Hi everyone...excellent forum you have here!! I will definitely be frequenting this area a lot as I am fairly new ...

  1. #1
    Registered User
    Join Date
    Feb 2005
    Posts
    14

    Converting an unsigned int to to unsigned long long (64 bit)

    Hi everyone...excellent forum you have here!! I will definitely be frequenting this area a lot as I am fairly new to the programming scene.

    Anyways, I'm writing this program and I'm trying to figure out a way to convert two existing unsigned ints into two u_int64_t (or equivalently unsigned long longs) due to the large data I'm working with. I know it basically deal with a cast, a shift of bits, and then an add...but I really need help getting to this. Any help would be appreciated...thanks!

  2. #2
    and the hat of wrongness Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    32,761
    Code:
    u_int64_t a = my_ul1;
    u_int64_t b = my_ul2;
    u_int64_t c = (b << 32) | a;
    Or do it with casts.
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.
    I support http://www.ukip.org/ as the first necessary step to a free Europe.

  3. #3
    Confused Magos's Avatar
    Join Date
    Sep 2001
    Location
    Sweden
    Posts
    3,145
    u_int64_t c = (b << 32) | a;
    How does that work with 32-bit registers?
    MagosX.com

    Give a man a fish and you feed him for a day.
    Teach a man to fish and you feed him for a lifetime.

  4. #4
    and the hat of wrongness Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    32,761
    Well you have to make sure b is at least cast to u_int64_t before the shift, otherwise you just lose all the bits off the end and end up with a big fat zero.
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.
    I support http://www.ukip.org/ as the first necessary step to a free Europe.

  5. #5
    ATH0 quzah's Avatar
    Join Date
    Oct 2001
    Posts
    14,826
    Quote Originally Posted by ninjacookies
    Anyways, I'm writing this program and I'm trying to figure out a way to convert two existing unsigned ints into two u_int64_t (or equivalently unsigned long longs) due to the large data I'm working with.
    What? You're converting two unsigned ints into two unsigned long longs? Um, ok...

    Code:
    unsigned int foo = 1, bar = 2;
    
    unsigned long long llfoo = foo, llbar = bar;
    I'm not sure I see where or why you're having a problem.

    Quzah.
    Hope is the first step on the road to disappointment.

  6. #6
    .
    Join Date
    Nov 2003
    Posts
    307
    The compiler should be able to promote ('automagically' cast, like the post above) the unsigned long into any other valid integer type. What you describe seems okay to me. What problem are you having?

  7. #7
    Registered User
    Join Date
    Feb 2005
    Posts
    14
    thanks a bunch for all your replies people, much appreciated

    I guess let me rephrase what I'm trying to do

    I'm trying to seperately convert each of two unsigned ints into unsigned long longs

    example:

    unsigned int a;
    unsigned int b;

    >>

    unsigned long long a;
    unsigned long long b;

    So just think in terms of each one being converted seperately...better yet, I should have just said 'im trying to convert an unsigned int into an unsigned long long.

    And I understand that the compiler should be able to promote the conversion automatically with a single declaration, but I don't think the conversion is going as it should, because the significant bits and low order bits are not being shifted, thus I'm ending up with a 19 digit output that is nowhere near what the actual value should be.

    That's why I asked if anyone could please help me in how to manually convert a 32bit unsigned int into a 64bit unsigned long long so that all low order and high order bits are shifted and wrapped around accordingly regardless of the input number.

    Thanks much

  8. #8
    Gawking at stupidity
    Join Date
    Jul 2004
    Location
    Oregon, USA
    Posts
    3,171
    There is nothing you have to do. Something else must be causing your weird 19-digit number:
    Code:
    itsme@dreams:~/C$ cat big.c
    #include <stdio.h>
    
    int main(void)
    {
      unsigned int a;
      unsigned long long b;
    
      a = 892374;
      b = a;
    
      printf("%u:%llu\n", a, b);
    
      return 0;
    }
    Code:
    itsme@dreams:~/C$ ./big
    892374:892374
    Maybe it would help if you showed us exactly what it is you're doing (i.e. your code).
    If you understand what you're doing, you're not learning anything.

  9. #9
    Registered User
    Join Date
    Feb 2005
    Posts
    14
    Code:
    #include <stdio.h>
    #include <sys/types.h>
    
    static unsigned cyc_hi = 0;
    static unsigned cyc_lo = 0;
    
    
    /* Set *hi and *lo to the high and low order bits of the cycle counter. */
    
    void access_counter(unsigned *hi, unsigned *lo)
    {
            /* Get cycle counter */
            asm("rdtsc; movl %%edx, %0; movl %%eax, %1"
                : "=r" (*hi), "=r" (*lo)
                : /* No input */
                : "%edx", "%eax");
    
    }
    
    
    
    u_int64_t get_cycles(void)
    
    {
    unsigned ncyc_hi, ncyc_lo;
    unsigned hi, lo, borrow;
    u_int64_t result;
    
    
    /* Get current value of cycle counter */
    access_counter(&ncyc_hi, &ncyc_lo);
    
    lo - ncyc_lo - cyc_lo;
    
    borrow = lo > ncyc_lo;
    hi = ncyc_hi - cyc_hi - borrow;
    
    
    
    result = (double) hi * (1 <<30) * 4 + lo;    
    
    return result;
    
    }
    
    
    main ()
    {
    
    u_int64_t start, end;
    
    start = get_cycles();
    usleep(1000000);
    end = get_cycles();
    
    printf("elapsed: %llu\n", end - start);
    }

    My program basically reads the high and low order bits of the cycle counter using assembly code and then passes the values to the access counter function which is called by getcycles, which 'should' return an unsigned 64 bit value to 'return'. So basically I want to convert *hi and *lo to unsigned long long and then convert this line
    result = (double) hi * (1 <<30) * 4 + lo;

    to the correct expression to represent an u_int64_t instead of a double.

  10. #10
    Registered User
    Join Date
    Oct 2001
    Posts
    2,934
    Using what Salem posted, I think this gives you the 64-bit value:
    Code:
    /* Get current value of cycle counter */
    access_counter(&ncyc_hi, &ncyc_lo);
    
    result = ncyc_hi;
    result <<= 32;
    result += ncyc_lo;
    return result;
    You can also create two 64-bit temps (as shown above), and do it in fewer steps. But I believe the problem is the print statement. I don't believe the following prints the 64-bit value correctly:
    Code:
    printf("elapsed: %llu\n", end - start);
    At least on my computer, using Dev-C++, it only prints 32-bits. I don't know how you print 64-bits.

  11. #11
    Registered User
    Join Date
    Mar 2004
    Posts
    536
    Quote Originally Posted by swoopy
    Using what Salem posted, I think this gives you the 64-bit value:
    Code:
    /* Get current value of cycle counter */
    access_counter(&ncyc_hi, &ncyc_lo);
    
    result = ncyc_hi;
    result <<= 32;
    result += ncyc_lo;
    return result;
    You can also create two 64-bit temps (as shown above), and do it in fewer steps. But I believe the problem is the print statement. I don't believe the following prints the 64-bit value correctly:
    Code:
    printf("elapsed: %llu\n", end - start);
    At least on my computer, using Dev-C++, it only prints 32-bits. I don't know how you print 64-bits.
    With gcc on my Windows XP box this works:

    Code:
    #include <stdio.h>
    #include <sys/types.h>
    
    /* 
     * just in case you want a function to hide the bit shifting 
     */
    
    u_int64_t make_longlong(u_int32_t, u_int32_t);
    
    int main ()
    {
    
      u_int64_t start, end, diff;
      u_int32_t hi, lo;
    
      hi = 0x12345678;
      lo = 0x9abcdef0;
    
      start = make_longlong(hi, lo);
    
      hi = 0x55555555;
      lo = 0x11111111;
    
      end = ((u_int64_t)hi << 32) | lo;
    
    
      diff = end - start;
    
      printf("end   = %llu  (%llx hex)\n", end, end);
      printf("start = %llu  (%llx hex)\n", start, start);
    
      printf("diff  = %llu  (%llx hex)\n", diff, diff);
    
      return 0;
    }
    
    /* if you want to make a function to hide the bit shifting 
     * here's a possibility
     */
    u_int64_t make_longlong(u_int32_t hi, u_int32_t lo)
    {
      return ((u_int64_t)hi << 32) | lo;
    }
    (If you run gcc -pedantic, it mentions that ISO C90 does not support the 'll' printf modifier.)

    Regards,

    Dave

  12. #12
    Yes, my avatar is stolen anonytmouse's Avatar
    Join Date
    Dec 2002
    Posts
    2,544
    Just for completeness, here's an entirely non-portable solution:
    Code:
    #include <windows.h>
    u_int64_t make_ulonglong(u_int32_t hi, u_int32_t lo)
    {
        ULARGE_INTEGER uli;
        uli.LowPart  = lo;
        uli.HighPart = hi;
        return uli.QuadPart;
    }

  13. #13
    Registered User
    Join Date
    Sep 2004
    Posts
    44
    ninjacookies,

    MSVC and some others require 'I64' as follows:
    Code:
    printf("elapsed: %I64u\n", end - start);

  14. #14
    Registered User
    Join Date
    Oct 2001
    Posts
    2,934
    >With gcc on my Windows XP box this works:
    Thanks for the info Dave. Maybe I've got an old version of gcc. I'll try your exact code tomorrow with Dev-C++ and see what happens.

    >(If you run gcc -pedantic, it mentions that ISO C90 does not support the 'll' printf modifier.)
    I'll give that a try too, and see if that warning shows.

  15. #15
    Registered User
    Join Date
    Oct 2001
    Posts
    2,934
    Here's my output with Dave's code:
    Code:
    end   = 286331153  (55555555 hex)
    start = 2596069104  (12345678 hex)
    diff  = 1985229345  (4320fedc hex)
    Which obviously isn't right. I've got Dev-C++ 4.9.8.0 (can't tell what version of gcc it's running, but there was no u_int64_t or u_int32_t, so I had to typedef them. It gave me this warning with pedantic:
    warning: ISO C89 does not support `long long'
    Time to update my compiler?

    On a side note, it's fairly easy to make a print function for a 64-bit int, which was what I did to verify my output.

Page 1 of 2 12 LastLast
Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Screwy Linker Error - VC2005
    By Tonto in forum C++ Programming
    Replies: 5
    Last Post: 06-19-2007, 03:39 PM
  2. Replies: 3
    Last Post: 05-13-2007, 09:55 AM
  3. Converted from Dev-C++ 4 to Dev-C++ 5
    By Wraithan in forum C++ Programming
    Replies: 8
    Last Post: 12-03-2005, 07:45 AM
  4. getting a headache
    By sreetvert83 in forum C++ Programming
    Replies: 41
    Last Post: 09-30-2005, 06:20 AM
  5. A Simple (?) Problem
    By Unregistered in forum C++ Programming
    Replies: 8
    Last Post: 10-12-2001, 05:28 AM

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21