问题
I have a uuid class that is part of a portable library that gets initialized with the following piece of code. It works fine under windows, but under linux it's not generating UUID's correctly.
uint32 data[4];
data[0] = rng.Get();
data[1] = rng.Get();
data[2] = rng.Get();
data[3] = rng.Get();
data[1] = (data[1] & 0xffffff0f) | 0x40;
data[2] = (data[2] & 0x7fffffff) | 0x40000000;
printf("12345678901234567890123456789012\n");
memcpy(uuid, data, 16);
for (int i = 0; i < 4; i++)
printf("%04X", data[i]);
printf("\n");
for (int i = 0; i < 16; i++)
printf("%02X", uuid[i]);
printf("\n");
The printf statements are me debugging it.
But, the numbers are messed up. Why are the bottom 4 bytes empty? And why is the first uuid printed, different from the last?
The platorm is 64bt linux on x86. This will always be run on x86 small endian architecture.
e.g. sample output
1st run
12345678901234567890123456789012
B6D2ADAF46CF624A581187F3670BBEE0
AFADD2B6D6E792FB4A62CF4600000000 // why is this different from the previous no?. also the last 4 bytes not set???
2nd run
12345678901234567890123456789012
96D6D234D5602743548FD812A0D96818
34D2D6965B65F32F432760D500000000 // same problem as earlier
Something is going haywire with the conversion.
This has now been solved. I don't care about endianess. The bytes are random anyway!
回答1:
It appears that the %X
specifier is expecting an int
-sized input to be passed, while you seem to be passing it an unsigned char
(isn't that what uuid[i]
is?).
Try doing this and see if it helps:
for (int i = 0; i < 16; i++) {
int temp = uuid[i];
printf("%02X", temp);
}
printf("\n");
Update - New theory
OK, I looked at it more carefully after reading Matthew's answer.
The issue is memcpy
along with the (unknown) type of uuid
. You copy the uint
s over uuid
. The first 4 bytes of uuid
are the little-endian representation of data[0]
, as should be expected.
Now one theory that could explain the rest is that uint32
is actually 8 bytes long instead of 4, so when you copy the first 16 bytes of data
onto uuid
we see in order:
- 4 LSB of
data[0]
, little endian - 4 MSB of
data[0]
(junk) - 4 LSB of
data[1]
, little endian - 4 MSB of
data[1]
(junk, for some reason all zeroes) - And nothing of
data[2]
anddata[3]
.
So what is sizeof(uint32)
equal to?
回答2:
The first 4 bytes of data
and uuid
are the same, but in reversed order - looks like an endianness issue.
- This is due to the printf printing each uint32 as one block, but the (unsigned?) chars in memory order.
The 2nd 4 bytes of data
and the 3rd 4 bytes of uuid
are also the same, but reversed. Similar issue.
Solve these two issues and the rest will probably fall into place.
回答3:
Try this for debugging instead
for (int i = 0; i < 4; i++)
printf("%04X ", data[i]);
printf("\n");
for (int i = 0; i < 16; i++)
printf("%02X ", uuid[i]);
printf("\n");
I just added a space after the 'X's.
回答4:
uint32 is not 32 bits in 64Bit OS, but 64 bits. I saw it here but I think it's true on all 64bit systems.
回答5:
Two things are happening here:
- the endian problem
- you are on a 64 bit machine, so the compiler aligns the (32bit)ints to the native word
In general, you cannot assume how the compiler lays things out in memory. You have to do it the old fashioned way: uuid[0] = data[0] >> 24 & 0xFF
来源:https://stackoverflow.com/questions/5427037/uuid-generator-problem