C (gcc) ендіатичний агностик, без стандартних ліб, 92 91 байт
h(n)- це однозначна цілочисельна-> шестигранна функція помічника.
f(x,p)приймає ціле число і char[8]покажчик. Результат - 8 байт charданих. ( Не припиняється на 0, якщо тільки абонент не робить цього.)
Припущення: набір символів ASCII. Доповнення 2, intтак що правильний зсув врешті-решт знижує біт знака, а перетворення на uint32_tв intне з’єднує біт-шаблон, якщо встановлено високий біт. intпринаймні 32-розрядна. (Ширше може дозволити йому працювати над реалізацією доповнення 1 або значущою величиною C).
Неприпущення: що-небудь щодо порядку виконання байтів або підписання char.
i;h(n){n&=15;return n>9?n+87:n+48;}f(x,p)char*p;{for(i=5;--i;x>>=8)*p++=h(x>>4),*p++=h(x);}
Спробуйте в Інтернеті! включаючи тестовий абонент, що використовує printf("%.8s\n", buf)для друку вихідного буфера без 0-кінця.
Безголівки:
int h(n){n&=15;return n>9 ? n+'a'-10 : n+'0';} // single digit integer -> hex
int i;
void ungolfed_f(x,p)char*p;{
for(i=5; --i; x>>=8) // LS byte first across bytes
*p++=h(x>>4), // MS nibble first within bytes
*p++=h(x);
}
Робота n&=15;всередині h(x)є беззбитковою; Там 6 байтів проти 3 для кожного, &15щоб виділити низьку риску в обох сайтах виклику.
,- це точка послідовності (або еквівалент у сучасній термінології), тому безпечно робити *p++= stuffдвічі в одному операторі, коли їх розділяє ,оператор.
>>на підписане ціле число визначається як арифметичне, так і логічне. GNU C визначає це як доповнення арифметики 2. Але на будь-якій машині доповнення будь-якого 2 це насправді не має значення, оскільки ми ніколи не дивимося на змінені 0 або копії біта знака. Оригінальний MSB з часом потрапить у низький байт без змін. Це не за ознакою / величиною, і я не впевнений у додатку 1.
Таким чином, це може бути переносним лише для 2-х реалізацій доповнення C. (Або де intце ширше , ніж 32 біта , тому біт 31 тільки частина величини.) Без знака -> підписали перетворення також munges біт-шаблон для негативних цілих чисел, так що &15на intб витягти тільки гризе вихідного беззнаковое значення на 2 з доповненням. Знову ж таки, якщо intвона не була ширшою за 32-бітну, тому всі входи невід'ємні.
Версія для гольфу має UB від падіння до кінця недійсної функції. Не повертати значення, просто щоб не оголосити його voidзамість за замовчуванням int. Сучасні компілятори вирішать це за умови активізації.
Мотивація: Я розглядав відповідь Asm на палець x86 або ARM, думав, що це може бути цікаво зробити це вручну на C, можливо, для відпрацьованого компілятором ASM як вихідної точки. Дивіться /programming/53823756/how-to-convert-a-number-to-hex щодо швидкодіючої швидкості x86, включаючи версію AVX512VBMI, яка містить лише 2 інструкції (але потрібні вектори управління для vpmultishiftqb та vpshufb так що не було б чудово для гольфу). Зазвичай для SIMD потрібна додаткова робота, щоб перевернути байт в порядок друку на маленькій ендіанській x86, тому цей байт-зворотний шестигранний вихід насправді простіший, ніж зазвичай.
Інші ідеї
Я розглядав можливість приймати ціле число за допомогою посилання та перебирати його байти char*за допомогою малоінтенсивного виконання C (наприклад, x86 або ARM). Але я не думаю, що це б значно заощадило.
Використовуючи sprintfробити 1 байт одночасно, 64 байти після гри в гольф:
int i;
void f(x,p)char*p;{
for(i=4;sprintf(p,"%.2x",x&255),--i;x>>=8)
p+=2;
}
Але якщо ми використовуємо функції, схожі на printf, ми можемо також замінити байт і зробити %xprintf всього цього, як відповідь @ JL2210 .