Tôi đã thấy các định nghĩa vĩ mô sau đây trong một cuốn sách mã hóa.
#define TRUE '/'/'/'
#define FALSE '-'-'-'
Không có lời giải thích ở đó.
Hãy giải thích cho tôi làm thế nào những điều này sẽ làm việc như TRUEvà FALSE.
Tôi đã thấy các định nghĩa vĩ mô sau đây trong một cuốn sách mã hóa.
#define TRUE '/'/'/'
#define FALSE '-'-'-'
Không có lời giải thích ở đó.
Hãy giải thích cho tôi làm thế nào những điều này sẽ làm việc như TRUEvà FALSE.
Câu trả lời:
Chúng ta hãy xem: '/' / '/'có nghĩa là nghĩa charđen /, chia cho chính charnghĩa đen '/'. Kết quả là một, mà âm thanh hợp lý cho TRUE.
Và '-' - '-'có nghĩa là nghĩa charđen '-', trừ đi từ chính nó. Đây là số không ( FALSE).
Có hai vấn đề với điều này: thứ nhất, nó không thể đọc được. Sử dụng 1và 0hoàn toàn tốt hơn. Ngoài ra, như TartanLlama và KerrekSB đã chỉ ra, nếu bạn định sử dụng định nghĩa đó, vui lòng thêm dấu ngoặc đơn xung quanh chúng để bạn không gặp phải bất ngờ nào:
#include <stdio.h>
#define TRUE '/'/'/'
#define FALSE '-'-'-'
int main() {
printf ("%d\n", 2 * FALSE);
return 0;
}
Điều này sẽ in giá trị của charchữ '-'(45 trên hệ thống của tôi).
Với dấu ngoặc đơn:
#define TRUE ('/'/'/')
#define FALSE ('-'-'-')
chương trình in chính xác bằng 0, mặc dù không có ý nghĩa gì khi nhân giá trị thật với số nguyên, nhưng đó chỉ là một ví dụ về loại lỗi không mong muốn có thể cắn bạn nếu bạn không nuôi dưỡng macro của mình.
ifthay vì nhân TRUEvới một số nguyên.
notx = TRUE- x;và hoạt động tốt. Ngoại trừ đó TRUE-FALSElà -44 (giả sử ASCII)
Nó chỉ là một cách viết khác
#define TRUE 1
#define FALSE 0
Biểu thức '/'/'/'sẽ chia giá trị char của '/'chính nó, kết quả sẽ cho 1.
Biểu thức '-'-'-'sẽ trừ đi giá trị char của '-'chính nó, kết quả sẽ cho 0.
Các dấu ngoặc xung quanh toàn bộ definebiểu thức bị thiếu, điều này có thể dẫn đến lỗi trong mã khi sử dụng các macro này. Câu trả lời của Jay khá tốt.
Một ví dụ về kịch bản "đời thực" trong đó việc quên dấu ngoặc có thể gây hại là việc sử dụng kết hợp các macro này với toán tử truyền kiểu C. boolVí dụ, nếu ai đó quyết định chuyển các biểu thức này sang C ++:
#include <iostream>
#define TRUE '/'/'/'
#define FALSE '-'-'-'
int main() {
std::cout << "True: " << (bool) TRUE << std::endl;
std::cout << "False: " << (bool) FALSE << std::endl;
return 0;
}
Đây là những gì chúng ta nhận được:
True: 0
False: -44
Vì vậy, (bool) TRUEsẽ thực sự đánh giá falsevà (bool) FALSEsẽ đánh giá true.
Nó tương đương với văn bản
#define TRUE 1
#define FALSE 0
Những gì biểu thức '/'/'/'thực sự làm là chia nhân vật /(bất kể giá trị số của nó là gì), vì vậy nó trở thành 1.
Tương tự, biểu thức '-'-'-'trừ nhân vật -khỏi chính nó và ước lượng 0.
Nó sẽ tốt hơn để viết
#define TRUE ('/'/'/')
#define FALSE ('-'-'-')
để tránh sự thay đổi ngẫu nhiên của các giá trị khi được sử dụng với các toán tử ưu tiên cao hơn khác.
Jay đã trả lời tại sao các giá trị của các biểu thức này là 0và 1.
Vì lợi ích lịch sử, những biểu hiện này '/'/'/'và '-'-'-'đến từ một trong những mục của Cuộc thi mã C bị xáo trộn quốc tế lần thứ nhất năm 1984 :
int i;main(){for(;i["]<i;++i){--i;}"];read('-'-'-',i+++"hell\
o, world!\n",'/'/'/'));}read(j,i,p){write(j/p+p,i---j,i/i);}
(Liên kết đến chương trình tại đây , có một gợi ý về những gì chương trình này làm trong trang IOCCC ở trên.)
Ngoài ra, nếu tôi nhớ chính xác các biểu thức này như các macro bị che khuất TRUEvà FALSEcũng được bao gồm trong cuốn sách "Obfuscated C và Other Mysteries" của Don Libes (1993).
Đó là cách vui nhộn để viết macro cho Truevà False.
Như nhiều lời giải thích đã được cung cấp /phương tiện một số 1 byte (theo ASCII) khi chia cho bản thân nó cung cấp cho bạn 1sẽ được điều trị như Truevà tương tự -một lần nữa một số byte khi trừ giá trị như nhau nó cung cấp cho bạn 0đó sẽ được hiểu làfalse
#define TRUE '/'/'/'
#define FALSE '-'-'-'
do đó chúng tôi có thể thay thế /hoặc -bằng bất kỳ char nào chúng tôi muốn, ví dụ:
#define TRUE '!'/'!'
#define FALSE 'o'-'o'
Sẽ giữ nguyên ý nghĩa như biểu thức ban đầu.
Hãy bắt đầu với sự thật. Bạn có thể đọc nó dưới dạng '/' / '/', có nghĩa là "ký tự '/' chia cho ký tự '/'". Vì mỗi ký tự, trong C, là một giá trị số (trên một byte), nên có thể được đọc là "giá trị ASCII của ký tự '/' chia cho giá trị ASCII của cùng một ký tự", có nghĩa là 1 (vì rõ ràng, x / x là 1). Do đó, TRUElà 1.
Vì FALSE, cùng một lý do: '-'-'-'đọc '-' - '-', tức là "giá trị ASCII của '-' trừ đi giá trị ASCII của '-'", bằng 0. Do đó, FALSElà 0.
Đây là một cách khó chịu để nêu rõ ràng.
'/'/'/'là 1 cho bất kỳ bộ ký tự hợp lệ nào , cho dù '/' == 47(như trong ASCII) hoặc '/' == 97(như trong EBCDIC) hoặc bất kỳ giá trị nào khác.
'/'tới 0. Giá trị đó được dành riêng cho ký tự null.