C (gcc) endian agnostisch, keine Standardbibliotheken, 92 91 Bytes
h(n)ist eine einstellige Ganzzahl-> Hex-Hilfsfunktion.
f(x,p)nimmt eine ganze Zahl und einen char[8]Zeiger. Das Ergebnis sind 8 Datenbytes char. ( Nicht 0-terminiert, es sei denn, der Anrufer tut dies.)
Annahmen: ASCII-Zeichensatz. Das 2er-Komplement, intso dass die Rechtsverschiebung schließlich das Vorzeichenbit verringert , und das Konvertieren von a uint32_tin intdas Bitmuster wird nicht beeinträchtigt, wenn das hohe Bit gesetzt ist. intist mindestens 32-Bit. (Weiter kann es bei 1-Komplement- oder C-Implementierungen mit Vorzeichengröße funktionieren).
Nichtannahmen: Alles über die Reihenfolge der Implementierung oder die Signatur von 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);}
Probieren Sie es online aus! einschließlich Testaufrufer printf("%.8s\n", buf)zum Drucken des Ausgabepuffers ohne 0-Terminierung.
Ungolfed:
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);
}
Doing n&=15;innen h(x)ist der Break-even; 6 Bytes dort gegen jeweils 3 &15, um das niedrige Knabbern an beiden Anrufstellen zu isolieren.
,ist ein Sequenzpunkt (oder ein Äquivalent in der modernen Terminologie), daher ist es sicher, *p++= stuffzweimal in einer Anweisung zu arbeiten, wenn dies vom ,Operator getrennt wird .
>>Eine vorzeichenbehaftete Ganzzahl wird durch die Implementierung entweder als arithmetisch oder als logisch definiert. GNU C definiert es als das Komplement der arithmetischen 2. Aber auf jeder 2er-Komplement-Maschine spielt es keine Rolle, weil wir niemals die eingeschobenen Nullen oder Kopien des Vorzeichenbits betrachten. Das ursprüngliche MSB wird schließlich unverändert in das Low-Byte gelangen. Dies ist bei Vorzeichen / Größe nicht der Fall, und ich bin mir über das Komplement von 1 nicht sicher.
Dies kann also möglicherweise nur auf 2-Komplement-C-Implementierungen portierbar sein. (Oder wo intes breiter als 32 Bit ist, so dass Bit 31 nur ein Teil der Größe ist.) Vorzeichenlose -> vorzeichenbehaftete Konvertierung mungiert auch das Bitmuster für negative ganze Zahlen, so dass &15ein intnur Halbbytes des ursprünglichen vorzeichenlosen Werts auf dem 2er-Komplement extrahiert. Wiederum, es intsei denn, es war breiter als 32-Bit, sodass alle Eingänge nicht negativ sind.
Bei der Golfversion fällt UB vom Ende einer nicht leeren Funktion ab. Einen Wert nicht zurückzugeben, nur um zu vermeiden, dass er voidanstelle des Standardwerts deklariert wird int. Moderne Compiler werden dies mit aktivierter Optimierung unterbrechen.
Motivation: Ich habe über eine x86- oder ARM Thumb asm-Antwort nachgedacht und dachte, es könnte Spaß machen, sie manuell in C auszuführen, möglicherweise für vom Compiler generierten asm als Ausgangspunkt. Unter /programming/53823756/how-to-convert-a-number-to-hex finden Sie Informationen zu geschwindigkeitseffizientem x86-ASM, einschließlich einer AVX512VBMI-Version, die nur zwei Anweisungen enthält (jedoch Kontrollvektoren für vpmultishiftqb und vpshufb benötigt) wäre also nicht toll für golf). Normalerweise erfordert SIMD zusätzliche Arbeit, um die Byte-Umkehrung in die Druckreihenfolge auf Little-Endian x86 durchzuführen, sodass diese byteumgekehrte Hex-Ausgabe tatsächlich einfacher als normal ist.
Andere Ideen
Ich habe überlegt, die Ganzzahl als Referenz zu nehmen und ihre Bytes mit char*einer Little-Endian-C-Implementierung (wie x86 oder ARM) zu durchlaufen. Aber ich denke nicht, dass das viel gespart hätte.
Verwenden sprintfSie jeweils 1 Byte, 64 Byte nach dem Golfen:
int i;
void f(x,p)char*p;{
for(i=4;sprintf(p,"%.2x",x&255),--i;x>>=8)
p+=2;
}
Wenn wir jedoch printf-ähnliche Funktionen verwenden, können wir genauso gut einen Byte-Swap durchführen und einen %xprintf des Ganzen wie die Antwort von @ JL2210 erstellen .