Dòng code mà một lập trình viên dày dặn từng viết khiến bạn sốc nhất là gì?

A: Micha Berger, từng học tại Dại học Yeshiva

=============

#define swap(x, y) (x ^= y ^= x ^= y)

Đó là một macro tiền xử lý trong C, tức là bạn sẽ thấy thứ gì đó đại loại kiểu

swap(this, that);

trong code của bạn, và trình biên dịch C nhận được từ bộ tiền xử lý đoạn mã

(this ^= that ^= this ^= that);

để biên dịch. Bạn không cần phải khai báo một biến tạm (temporary) như bạn sẽ làm trong phần lớn những đoạn mã thực hiện swap, nó không mang kiểu rõ ràng (type specific) và đoạn mã sẽ chạy với bất kỳ kiểu dữ liệu nào hỗ trợ toán tử exclusive or (XOR). Tôi sẽ giải thích một chút về cách hoán đổi của nó, song tại sao bạn không thử tự mình làm phép toán boolean nhỉ? (Tôi sẽ đưa vào trong comment đầu tiên) Và

Đây là đoạn mã bị lỗi khiến chúng ta phải xem xét lại:

swap(arr[i], arr[j]);

Trong trường hợp i == j thì. arr[i] và arr[j] là cùng một biến trong bộ nhớ và toán tử “^=” đầu tiên sẽ ghi đè lên cả hai. Từ đó: arr[i] == arr[j] == 0.

Vậy, nó chỉ chạy khi hai biến chỉ đến những địa chỉ khác nhau trong bộ nhớ thôi nhé.

Dù rất sốc vì mức độ thông minh của nó, song nó vẫn cực ngu.

[COMMENT]

Logic là như sau. Tôi sẽ tách ra các mỗi phần tương ứng của x và y (ta lấy x, biến thành x’, và thành x’’… Tương tự với y’).

{x’ = x ^ y}

{y’ = x’ ^ y == x ^ y ^ y == x}

{x’’ == x’ ^ y’ == x ^ y ^ x == y}

Vì thếm, bạn chỉ còn biến {x} giữ giá trị {y} và biến {y} giữ giá trị ban đầu của {x}.

Song, trong trường hợp macro này gặp lỗi ấy, viết rộng ra sẽ là

(array[i] ^= array[j] ^= array[i] ^= array[j])

Chậc, ví dụ {i == j == 2} chẳng hạn, thì sẽ là:

(array[2] ^= array[2] ^= array[2] ^= array[2])

và phép gán đầu tiên ấy là

array[2]’ = array[2] ^ array[2] == 0

— lúc này bạn đã gán cả “x” và “y” mất rồi! Vì vậy, mọi thứ còn lại sẽ chỉ là

array[2]’’ = 0 ^ 0 = 0

Theo: Vũ Cường

Leave a Reply

Your email address will not be published. Required fields are marked *