Неявное преобразование или приведение?

У меня есть функция, которая чередует биты 32-битных слов и возвращает 64-битный результат. В этом простом тестовом примере 3 нижних байта верны, а содержимое 5 верхних байтов неверно. intToBin_32 и intToBin_64 являются вспомогательными функциями для просмотра двоичного представления аргументов и возврата значения val. Я поместил приведение от 32-разрядного типа к 64-разрядному типу везде, где я думаю, что они необходимы, но я все еще вижу это неожиданное (по крайней мере для меня) поведение. Здесь происходит неявное преобразование, или есть какая-то другая причина, которая не работает правильно?

#include <stdint.h>
#include <stdio.h>

struct intString_32 {char bstr [32 + 1 + 8];};
struct intString_64 { char bstr [64 + 1 + 8];};

intString_32 intToBin_32(int a)
{
intString_32 b;

for (int i = 0; i < 8; i++)
{
for (int j = 0; j < 5; j++)
{
if (j != 4)
{
b.bstr[5*i + j] = * ((a & (1 << (31 - (4*i + j)))) ? "1" : "0");
}

else
{
b.bstr[5*i + j] = 0x20;
}
}
}

b.bstr[40] = * ( "\0" );

return b;
}

intString_64 intToBin_64(long long a)
{
intString_64 b;

for (int i = 0; i < 8; i++)
{
for (int j = 0; j < 9; j++)
{
if (j != 8)
{
b.bstr[9*i + j] = * ((a & (1 << (63 - (8*i + j)))) ? "1" : "0");
}

else
{
b.bstr[9*i + j] = 0x20;
}
}
}

b.bstr[72] = * ( "\0" );
return b;
}

uint64_t interleaveBits(unsigned int a, unsigned int b)
{
uint64_t retVal = 0;

for (unsigned int i = 0; i < 32; i++)
{
retVal |= (uint64_t)((uint64_t)((a >> i) & 0x1)) << (2*i);
retVal |= (uint64_t)((uint64_t)((b >> i) & 0x1)) << (2*i + 1);
}

return retVal;
}

int main(int arc, char* argv)
{
unsigned int foo = 0x0004EDC7;
unsigned int bar = 0x5A5A00FF;
uint64_t bat = interleaveBits(foo, bar);

printf("foo: %s \n", intToBin_32(foo).bstr);
printf("bar: %s \n", intToBin_32(bar).bstr);
printf("bat: %s \n\n", intToBin_64(bat).bstr);
}

-2

Решение

Через отладку я заметил, что это ваш intToBin_64 что неправильно, если быть точным, в этой строке:

b.bstr[9*i + j] = * ((a & (1 << (63 - (8*i + j)))) ? "1" : "0");

внимательнее посмотрим на смену:

(1 << (63 - (8*i + j)))

Буквальный 1 является целым числом, однако смещение целого числа более чем на 31 бит является неопределенным поведением. Сдвиньте длиннее вместо:

b.bstr[9*i + j] = * ((a & (1ll << (63 - (8*i + j)))) ? "1" : "0");
2

Другие решения

Других решений пока нет …

По вопросам рекламы ammmcru@yandex.ru
Adblock
detector