using 64-bit integers on 32-bit machine

S

seung

Hi,

I'm trying to use uint64_t by #including stdint.h in C on 32-bit
machine. However, I can't seem to get the right value for shifting,
for example:

for(i = 0; i < 64; i++)
{
c = 1 << i;
printf(" %d : %x\n", i, c);
}

gives the following output

0 : 1
1 : 2
2 : 4
3 : 8
4 : 10
5 : 20
6 : 40
7 : 80
8 : 100
9 : 200
10 : 400
11 : 800
12 : 1000
13 : 2000
14 : 4000
15 : 8000
16 : 10000
17 : 20000
18 : 40000
19 : 80000
20 : 100000
21 : 200000
22 : 400000
23 : 800000
24 : 1000000
25 : 2000000
26 : 4000000
27 : 8000000
28 : 10000000
29 : 20000000
30 : 40000000
31 : 80000000
32 : 1
33 : 2
34 : 4
35 : 8
36 : 10
37 : 20
38 : 40
39 : 80
40 : 100
41 : 200
42 : 400
43 : 800
44 : 1000
45 : 2000
46 : 4000
47 : 8000
48 : 10000
49 : 20000
50 : 40000
51 : 80000
52 : 100000
53 : 200000
54 : 400000
55 : 800000
56 : 1000000
57 : 2000000
58 : 4000000
59 : 8000000
60 : 10000000
61 : 20000000
62 : 40000000
63 : 80000000


Anyone know what the problem is, and what the correct solution is for
such use?


Thanks,
-Seung
 
I

Ian Collins

seung said:
Hi,

I'm trying to use uint64_t by #including stdint.h in C on 32-bit
machine. However, I can't seem to get the right value for shifting,
for example:
What's wrong with the answers you received on comp.std.c?
 
S

Spoon

seung said:
I'm trying to use uint64_t by #including stdint.h in C on 32-bit
machine. However, I can't seem to get the right value for shifting,
for example:

for(i = 0; i < 64; i++)
{
c = 1 << i;
printf(" %d : %x\n", i, c);
}

c = 1ULL << i;
printf("%d : %llx\n", i, c);
(Assuming uint64_t c)
 
M

Martin Ambuhl

seung said:
Hi,

I'm trying to use uint64_t by #including stdint.h in C on 32-bit
machine. However, I can't seem to get the right value for shifting,
for example:

for(i = 0; i < 64; i++)
{
c = 1 << i;
printf(" %d : %x\n", i, c);
}

gives the following output [snipped]


Anyone know what the problem is, and what the correct solution is for
such use?
#include <stdio.h>
#include <stdint.h>
#include <inttypes.h>
#include <limits.h>

int main(void)
{
unsigned i;
uint64_t c;

printf("For this implementation,\n"
"sizeof(uint64_t) = %zu, * CHAR_BIT = %zu\n"
"and the macro PRIx64 expands to " PRIx64
".\n Check to make sure these are OK.\n\n", sizeof(uint64_t),
sizeof(uint64_t) * CHAR_BIT);
for (i = 0; i < 64; i++) {
c = 1llu << i;
printf(" %u : %" PRIx64 "\n", i, c);
}
return 0;
}



[output]
For this implementation,
sizeof(uint64_t) = 8, * CHAR_BIT = 64
and the macro PRIx64 expands to llx.
Check to make sure these are OK.

0 : 1
1 : 2
2 : 4
3 : 8
4 : 10
5 : 20
6 : 40
7 : 80
8 : 100
9 : 200
10 : 400
11 : 800
12 : 1000
13 : 2000
14 : 4000
15 : 8000
16 : 10000
17 : 20000
18 : 40000
19 : 80000
20 : 100000
21 : 200000
22 : 400000
23 : 800000
24 : 1000000
25 : 2000000
26 : 4000000
27 : 8000000
28 : 10000000
29 : 20000000
30 : 40000000
31 : 80000000
32 : 100000000
33 : 200000000
34 : 400000000
35 : 800000000
36 : 1000000000
37 : 2000000000
38 : 4000000000
39 : 8000000000
40 : 10000000000
41 : 20000000000
42 : 40000000000
43 : 80000000000
44 : 100000000000
45 : 200000000000
46 : 400000000000
47 : 800000000000
48 : 1000000000000
49 : 2000000000000
50 : 4000000000000
51 : 8000000000000
52 : 10000000000000
53 : 20000000000000
54 : 40000000000000
55 : 80000000000000
56 : 100000000000000
57 : 200000000000000
58 : 400000000000000
59 : 800000000000000
60 : 1000000000000000
61 : 2000000000000000
62 : 4000000000000000
63 : 8000000000000000
 
A

Army1987

Hi,

I'm trying to use uint64_t by #including stdint.h in C on 32-bit
machine. However, I can't seem to get the right value for shifting,
for example:

for(i = 0; i < 64; i++)
{
c = 1 << i;
printf(" %d : %x\n", i, c);
}

gives the following output

0 : 1
1 : 2
2 : 4 [snip]
30 : 40000000
31 : 80000000
32 : 1
33 : 2 [snip]
62 : 40000000
63 : 80000000


Anyone know what the problem is, and what the correct solution is for
such use?
Note that 1 << i is evaluated to its type (the type resulting from
integer promotions of 1, which is an int, and i, whose declaration
you didn't show), and only then it is converted to the type of c.
Replace 1 with 1ULL.
Also "%x" is the conversion specifier for unsigned int (often 32
bits even on 64-bits machines), for uint64_t you need the macro
PRIx64 (e.g. " %d : %" PRIx64 "\n"), most likely to be "llx" for
unsigned long long.
 
D

David Thompson

Note that 1 << i is evaluated to its type (the type resulting from
integer promotions of 1, which is an int, and i, whose declaration
you didn't show), and only then it is converted to the type of c.

Each of 1 and i is subject to integer promotions, yes. However, your
'and' seems to imply there is some relation _between_ them.

_Most_ arithmetic operators do what are called the usual arithmetic
conversions: each operand separately is subject to integer promotions
and then if they are (still) different types they are both converted
to, informally, a 'least common' type; usually this is the larger of
the two, so only the smaller is really converted.
E.g.: 3 + 4L the 3 is converted to long to match the 4L.

But not shifts. They only do integer promotions. In 1 << i the 1
remains int even if i is long long or int2048_t.
Replace 1 with 1ULL.

Or (uint64_t)1 . Which more clearly represents the intent, and avoids
the risk, albeit a very tiny one, that long long is more than 64 bits.
Also "%x" is the conversion specifier for unsigned int (often 32
bits even on 64-bits machines), for uint64_t you need the macro
PRIx64 (e.g. " %d : %" PRIx64 "\n"), most likely to be "llx" for
unsigned long long.

Right.

- formerly david.thompson1 || achar(64) || worldnet.att.net
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,755
Messages
2,569,536
Members
45,009
Latest member
GidgetGamb

Latest Threads

Top