Trong khi đoạn mã này không tuân thủ tiêu chuẩn, gcc sẽ biên dịch nó và đầu ra phù hợp với phân tích của tôi về mã. Đáng buồn thay, tôi không thể thực sự giải thích đầu ra mà không có ngữ cảnh nhiều hơn một chút. Nếu tôi bỏ qua backspaces, đầu ra trông giống như sau:
C!o!r!s!i!...
Để phân tích mã, chúng tôi sẽ bắt đầu bằng cách định dạng nó một chút:
#include <stdio.h>
char* _ ="XxTIHRCXCxTIHRXRCxTIHXHRCxTIXIHRCxTXTIHRCxXxTIHRCX";
int main(int l){
for(l+=7; l != putchar(010); ++l); // 010 = 8 -> backspace char
if(*(++_))
main(
*_ != 88 ? // *_ != 'X'
(putchar(*_^073) | putchar(33)) & 1 : // 33 = '!'
0xffff2a8b);
}
Dưới đây là một vài điều đáng chú ý trước khi chúng tôi đi xa hơn:
- Nếu putchar thành công, nó trả về thẻ đã được chuyển.
- Trong C, các số bắt đầu bằng 0 thực sự là octals chứ không phải số thập phân. Vì vậy, 010 thực sự là số thập phân 8.
Bây giờ nhận thấy rằng bất cứ khi nào _ con trỏ được outputed, nó XORed với giá trị bát phân 073. Nếu chúng ta áp dụng điều này trên toàn bộ chuỗi chúng tôi nhận được:
cCorsixcxCorsicixCorscsixCorcrsixCocorsixCcCorsixc
Điều này bắt đầu giống với đầu ra mà chúng ta đã thấy trước đó. Hãy tiếp tục bằng cách phân tích một vài dòng thú vị hơn:
for(l+=7; l != putchar(010); ++l); // 010 = 8 -> backspace char
Điểm của dòng này là tạo ra một loạt các khoảng trống. Nếu l bằng 1 thì nó sẽ chỉ xuất ra một backspace. Nhưng nếu nó tương đương với cái gì đó khác, nó sẽ trở nên bối rối trên bãi chứa tải trọng của các ký tự. Hành vi này phụ thuộc vào cách gọi chính. Khi khởi động, nó xuất hiện luôn được gọi với giá trị 1 (không biết tại sao).
Bây giờ, hãy xem các thành phần của cuộc gọi chính đệ quy.
(putchar(*_^073) | putchar(33)) & 1 : // 33 = '!'
Đây là nhánh đầu tiên có thể. Đầu tiên nó xuất ra, một trong các ký tự XORed và sau đó nó xuất ra một '!' char. Nếu bạn nhìn vào mẫu bit 33, bạn sẽ nhận thấy rằng (x | 33) & 1 sẽ luôn luôn đánh giá là 1. Vì vậy, trong trường hợp này chúng ta chỉ xuất ra một ký tự backspace duy nhất trong vòng lặp for. Mặt khác, nhánh thứ hai hơi phức tạp hơn vì giá trị được chuyển đến chính không phải là 1. Nếu bạn nhìn kỹ vào đầu ra của chương trình, bạn sẽ nhận thấy rằng nó tạo ra một tải trọng xe tải của một không gian nhất định tại một vị trí nhất định. đặt trong chuỗi. Không có bối cảnh, tôi không thể nói mục đích là gì.
Bây giờ chúng ta có tất cả các mảnh, chúng ta hãy viết lại đoạn code:
#include <stdio.h>
#define BIG_CONSTANT 42 // Not the actual value.
int main() {
char* str = "cCorsixcxCorsicixCorscsixCorcrsixCocorsixCcCorsixc";
putchar(8);
char* c = str;
while (*c != '\0') {
if (*c != 'c') { // 'X'^073 = 'c'
putchar(*c);
putchar('!');
putchar(8);
}
else {
for (int i = 0; i < BIG_CONSTANT; ++i)
putchar(8);
}
c++;
}
}
C của tôi là một chút gỉ vì vậy đây có thể không biên dịch/chạy. Nó vẫn sẽ cung cấp cho bạn một ý tưởng tốt về những gì đang xảy ra.
EDIT: Tôi đã trễ một chút khi đăng câu trả lời của mình và tôi nhận ra rằng bảng điều khiển của tôi đang in không gian trở lại một chút để thay vì chỉ xóa các ký tự. Vì vậy, đó là lý do tại sao tôi phần nào hiểu sai đầu ra. Vì vậy, giống như câu trả lời được chấp nhận nói, nếu bạn thực sự xử lý các không gian chính xác, nó sẽ in ra Corsix !.
Eschew obfuscation. –
Đặt lửa cho đoạn mã này. –
@Fred Larson: Tôi googled, nhưng tôi không thể tìm thấy bất kỳ thông tin có liên quan. Bạn có thể chia sẻ một số ánh sáng? – Chan