mam następujący prosty program, który korzysta z unii do konwersji pomiędzy całkowitej 64 bitowej oraz odpowiadającego mu tablicy bajtów:C/C++ Konwersja 64 bitową liczbę całkowitą do tablicy char
union u
{
uint64_t ui;
char c[sizeof(uint64_t)];
};
int main(int argc, char *argv[])
{
u test;
test.ui = 0xabcdefLL;
for(unsigned int idx = 0; idx < sizeof(uint64_t); idx++)
{
cout << "test.c[" << idx << "] = 0x" << hex << +test.c[idx] << endl;
}
return 0;
}
co by się spodziewać jako wyjście jest:
test.c[0] = 0xef
test.c[1] = 0xcd
test.c[2] = 0xab
test.c[3] = 0x89
test.c[4] = 0x67
test.c[5] = 0x45
test.c[6] = 0x23
test.c[7] = 0x1
Ale to, co rzeczywiście się znajduje:
test.c[0] = 0xffffffef
test.c[1] = 0xffffffcd
test.c[2] = 0xffffffab
test.c[3] = 0xffffff89
test.c[4] = 0x67
test.c[5] = 0x45
test.c[6] = 0x23
test.c[7] = 0x1
widzę to na Ubuntu LTS 14.04 z GCC.
Od pewnego czasu próbuję to zrozumieć. Dlaczego pierwsze 4 elementy tablicy znaków wyświetlane są jako 32-bitowe liczby całkowite, z dodaniem do nich 0xffffff? I dlaczego tylko pierwsze 4, dlaczego nie wszystkie?
Co ciekawe, kiedy używam tablicy do zapisu w strumieniu (co było pierwotnym celem całego obiektu), poprawne wartości są zapisywane. Porównywanie tablicy char przez char oczywiście prowadzi do problemów, ponieważ pierwsze 4 znaki nie są równe 0xef, 0xcd i tak dalej.
rzutować jako '(char *)', a następnie odczytać 4 bajty ...? – SteJ
Bez zmian. Poza tym zawsze mogę maskować znak za pomocą 0x000000ff, aby uzyskać oczekiwane wartości. Po prostu interesuje mnie przyczyna tego zachowania. – tickferno
Najwyraźniej twoja implementacja podpisała znaki. Zwykła promocja z liczbami całkowitymi spowoduje podpisanie rozszerzenia. – ewd