Thuyết bất khả tri C (gcc) , không có libs chuẩn, 92 91 byte
h(n)là một số nguyên một chữ số-> hàm trợ giúp hex.
f(x,p)lấy một số nguyên và một char[8]con trỏ. Kết quả là 8 byte chardữ liệu. ( Không kết thúc 0 trừ khi người gọi thực hiện việc đó.)
Giả định: bộ ký tự ASCII. Bổ sung của 2 intvì vậy sự thay đổi bên phải cuối cùng sẽ làm giảm bit dấu và chuyển đổi uint32_tthành intkhông thay đổi mẫu bit nếu bit cao được đặt. intít nhất là 32 bit. (Rộng hơn có thể cho phép nó hoạt động trên các triển khai C bổ sung hoặc cường độ ký hiệu 1).
Không giả định: bất cứ điều gì về thứ tự byte thực hiện hoặc chữ ký của 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);}
Hãy thử trực tuyến! bao gồm cả người gọi kiểm tra sử dụng printf("%.8s\n", buf)để in bộ đệm đầu ra mà không kết thúc 0.
Ung dung:
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);
}
Làm n&=15;bên trong h(x)là hòa vốn; 6 byte ở đó so với 3 mỗi cái &15để cô lập mức độ thấp ở cả hai trang web cuộc gọi.
,là một điểm thứ tự (hoặc tương đương theo thuật ngữ hiện đại), do đó, an toàn để thực hiện *p++= stuffhai lần trong một câu lệnh khi được phân tách bởi ,toán tử.
>>trên số nguyên đã ký được triển khai - được định nghĩa là số học hoặc logic. GNU C định nghĩa nó là phần bù 2 của số học. Nhưng trên máy bổ sung của bất kỳ 2 nào, điều đó không thực sự quan trọng bởi vì chúng tôi không bao giờ nhìn vào 0 hoặc các bản sao của bit dấu được thay đổi. MSB ban đầu cuối cùng sẽ chuyển xuống byte thấp không thay đổi. Đây không phải là trường hợp về dấu hiệu / cường độ và tôi không chắc chắn về phần bù của 1.
Vì vậy, điều này chỉ có thể được thực hiện cho 2 triển khai C bổ sung. (Hoặc nơi intlà rộng hơn so với 32 bit để cắn 31 chỉ là một phần của độ lớn.) Unsigned -> chuyển đổi ký cũng munges bit-khuôn mẫu cho số nguyên âm, vì vậy &15trên intsẽ chỉ trích Nibbles giá trị unsigned gốc trên bổ sung 2 của. Một lần nữa, trừ khi intlà rộng hơn so với 32-bit vì vậy tất cả đầu vào là không âm.
Phiên bản chơi gôn có UB từ phần cuối của hàm không trống. Không trả về giá trị, chỉ để tránh khai báo voidthay vì mặc định int. Trình biên dịch hiện đại sẽ phá vỡ điều này với tối ưu hóa được kích hoạt.
Động lực: Tôi đã xem xét câu trả lời asm x86 hoặc ARM Thumb, nghĩ rằng có thể rất vui khi thực hiện thủ công trong C, có thể lấy asm do trình biên dịch tạo làm điểm bắt đầu. Xem /programming/53823756/how-to-convert-a-number-to-hex để biết x86 asm hiệu quả tốc độ, bao gồm phiên bản AVX512VBMI chỉ có 2 hướng dẫn (nhưng cần vectơ điều khiển cho vpmultishiftqb và vpshufb vì vậy sẽ không tốt cho golf). Thông thường, cần thêm công việc để SIMD đảo ngược byte thành thứ tự in trên x86 endian nhỏ, do đó, đầu ra hex đảo ngược byte này thực sự dễ dàng hơn bình thường.
Những ý tưởng khác
Tôi đã xem xét việc lấy số nguyên bằng cách tham chiếu và lặp qua các byte của nó char*, trên một triển khai C nhỏ về cuối (như x86 hoặc ARM). Nhưng tôi không nghĩ rằng sẽ tiết kiệm được nhiều.
Sử dụng sprintfđể thực hiện 1 byte mỗi lần, 64 byte sau khi chơi gôn:
int i;
void f(x,p)char*p;{
for(i=4;sprintf(p,"%.2x",x&255),--i;x>>=8)
p+=2;
}
Nhưng nếu chúng ta đang sử dụng các hàm giống như printf, chúng ta cũng có thể trao đổi byte và thực hiện một %xprintf của toàn bộ điều như câu trả lời của @ JL2210 .