# Thread: Converting an unsigned int to to unsigned long long (64 bit)

1. ## 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. 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.

3. u_int64_t c = (b << 32) | a;
How does that work with 32-bit registers?

4. 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.

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.

6. 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. 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. 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).

9. 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. 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. 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. 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;
}```

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

14. >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. 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.