Tại sao loại boolean trong C ++ hỗ trợ ++ nhưng không -?


29

Tại sao toán tử --không tồn tại cho bool trong khi nó lại cho toán tử ++?

Tôi đã thử trong C ++ và tôi không biết câu hỏi của mình có áp dụng cho ngôn ngữ khác không. Tôi cũng sẽ vui mừng khi biết.

Tôi biết , tôi có thể sử dụng toán tử ++với bool. Nó làm cho bất kỳ bool bằng với đúng.

bool b = false;
b++;
// Now b == true.

Tại sao chúng ta không thể sử dụng toán tử --theo cách ngược lại?

bool b = true;
b--;
// Now b == false;

Nó không hữu ích lắm, nhưng tôi tò mò.


8
Câu hỏi này trên StackOverflow có thể được khai sáng.
Blrfl

Vì vậy, lý do lịch sử. Cảm ơn vi đương link. Bạn có thể viết một câu trả lời và tôi đặt nó như đã giải quyết?
aloisdg nói Phục hồi Monica

Các liên kết một mình không tạo ra câu trả lời hay và không có cơ chế tốt để đánh dấu câu hỏi về sự trùng lặp của một điều gì đó trên một trang web SE khác.
Blrfl

1
Vì vậy, chúng ta nên mở một chủ đề trong meta.stackexchange.com hoặc một cái gì đó. Tôi nghĩ rằng bạn nên nhận được một số nghiệp cho liên kết tốt và nếu ai đó nâng đỡ bạn, tác giả từ câu trả lời ban đầu sẽ nhận được một số nghiệp. Trong thực tế, câu hỏi ban đầu cũng sẽ nhận được một số nghiệp.
aloisdg nói Phục hồi Monica

2
Các trang web dups chéo @aloitorg là một vấn đề cũ trên MSO. Theo đuổi các câu hỏi được liên kết để có cái nhìn đầy đủ hơn về nó.

Câu trả lời:


53

Ngày xưa của C, không có kiểu boolean. Mọi người đã sử dụng intđể lưu trữ dữ liệu boolean và nó hoạt động chủ yếu. Zero là sai và mọi thứ khác đều đúng.

Điều này có nghĩa là nếu bạn lấy int flag = 0;và sau đó flag++, giá trị sẽ là đúng. Điều này sẽ hoạt động bất kể giá trị của cờ là bao nhiêu (trừ khi bạn đã làm rất nhiều, nó cuộn lại và bạn trở về số 0, nhưng hãy bỏ qua điều đó) - tăng cờ khi giá trị của nó là 1 sẽ cho 2, vẫn là thật.

Một số người đã sử dụng điều này để đặt vô giá trị boolean thành true. Tôi không chắc nó đã trở thành thành ngữ , nhưng trong một số mã.

Điều này không bao giờ có tác dụng --, bởi vì nếu giá trị là bất cứ thứ gì ngoài 1 (có thể là nó), thì giá trị vẫn sẽ không sai. Và nếu nó đã sai ( 0) và bạn đã thực hiện một toán tử giảm dần trên nó, thì nó sẽ không sai.

Khi chuyển mã từ C sang C ++ trong những ngày đầu, điều rất quan trọng là mã C có trong C ++ vẫn có thể hoạt động. Và như vậy, trong đặc tả cho C ++ (phần 5.2.6 (trên trang 71)), nó đọc:

Giá trị thu được bằng cách áp dụng một postfix ++ là giá trị mà toán hạng đã có trước khi áp dụng toán tử. [Lưu ý: giá trị thu được là bản sao của giá trị ban đầu] Toán hạng sẽ là giá trị có thể sửa đổi. Loại toán hạng sẽ là loại số học hoặc con trỏ đến loại đối tượng hoàn chỉnh. Sau khi kết quả được ghi chú, giá trị của đối tượng được sửa đổi bằng cách thêm 1 vào nó, trừ khi đối tượng có kiểu bool, trong trường hợp đó, nó được đặt thành true. [Lưu ý: việc sử dụng này không được chấp nhận, xem phụ lục D.]

Toán hạng của postfix - được giảm tương tự cho toán tử postfix ++, ngoại trừ toán hạng sẽ không phải là kiểu bool.

Điều này một lần nữa được đề cập trong phần 5.3.2 (đối với toán tử tiền tố - 5.2.6 là về hậu tố)

Như bạn có thể thấy, phần này không được dùng nữa (Phụ lục D trong tài liệu, trang 709) và không nên sử dụng.

Nhưng đó là lý do tại sao. Và đôi khi bạn có thể thấy mã. Nhưng đừng làm điều đó.


5
"Một số người đã sử dụng điều này để đặt vô điều kiện một giá trị boolean thành true." Chúng ta hãy gọi họ là những kẻ ngu ngốc, không phải người.
Ded

@Ded repeatator: Có thể đó là vấn đề về hiệu suất: tải một giá trị vào một biến có thể mất nhiều chu kỳ bộ xử lý hơn là tăng biến. Tất nhiên, điều này có lẽ không quan trọng trên các máy tính hiện đại.
Giorgio

1
@Giorgio đó là khá có khả năng. Hãy nhớ rằng C được viết để khớp với tập lệnh PDP-7 và PDP-11 có các chỉnh sửa khác. Từ điều này - "Mọi người thường đoán rằng chúng được tạo ra để sử dụng các chế độ địa chỉ tự động tăng và giảm tự động do DEC PDP-11 cung cấp, trong đó C và Unix lần đầu tiên trở nên phổ biến. Điều này là không thể, vì không có PDP- 11 khi B được phát triển. Tuy nhiên, PDP-7 đã có một vài ô nhớ 'tự động tăng', với đặc tính là một tham chiếu bộ nhớ gián tiếp thông qua chúng làm tăng ô. "

@Ded repeatator: Trong mã sử dụng số nguyên cho booleans, một biến được tăng cho mỗi ... bất cứ điều gì ... có thể đóng vai trò là một bộ đếm (tăng bao nhiêu lần) và như một boolean (nó đã được tăng lên ở tất cả hoặc không phải).
Keith Thompson


1

Để hiểu ý nghĩa lịch sử của câu hỏi này, bạn phải xem xét trường hợp của Therac-25. Therac-25 là một thiết bị y tế cung cấp bức xạ cho bệnh nhân ung thư. Nó đã bị ảnh hưởng bởi các thực tiễn lập trình xấu đã góp phần vào hồ sơ theo dõi an toàn kém của nó (với nhiều cái chết được quy cho nó).

http://cifts.cs.vt.edu/prof Professionism / Terac_25 / Therac_1.html

(đi đến cuối trang 3)

Mỗi lần vượt qua thói quen Kiểm tra thiết lập sẽ tăng kiểm tra vị trí collimator trên, một biến được chia sẻ có tên Class3. Nếu Class3 là khác không, có sự không nhất quán và điều trị không nên tiến hành. Giá trị 0 cho Class3 chỉ ra rằng các tham số liên quan phù hợp với điều trị và chùm tia không bị ức chế.

...

Trong quá trình thiết lập máy, Set-Up Test sẽ được thực thi hàng trăm lần kể từ khi nó tự lên lịch lại để chờ các sự kiện khác xảy ra. Trong mã, biến Class3 được tăng thêm một trong mỗi lần chuyển qua Kiểm tra thiết lập. Do biến Class3 là 1 byte, nên nó chỉ có thể chứa giá trị tối đa là 255 thập phân. Do đó, cứ sau 256 lần chuyển qua mã Kiểm tra thiết lập, biến sẽ tràn và có giá trị bằng không. Điều đó có nghĩa là cứ sau 256 lần vượt qua Kiểm tra thiết lập, collimator trên sẽ không được kiểm tra và lỗi collimator trên sẽ không được phát hiện. Sự tiếp xúc quá mức xảy ra khi người vận hành nhấn nút "set" tại thời điểm chính xác mà Class3 lăn qua không. Do đó, Chkcol đã không được thực thi và F $ mal không được đặt để biểu thị collimator phía trên vẫn ở vị trí ánh sáng trường. Phần mềm bật 25 MeV đầy đủ mà không có mục tiêu tại chỗ và không quét. Kết quả là chùm tia điện tử tập trung cao, bị tán xạ và làm chệch hướng bởi gương thép không gỉ đang ở trên đường đi.

Therac-25 đã sử dụng một cái gì đó tương tự như operator++trên a bool. Tuy nhiên, ngôn ngữ lập trình họ sử dụng không phải là C ++ và kiểu dữ liệu của họ thì không bool. Tuy nhiên, không giống như bảo đảm trong C ++, một loại số nguyên thông thường chỉ đơn giản là tiếp tục tăng lên. Kiểu dữ liệu của họ tương đương với uint8_t.

C ++ đã quyết định giữ operator++xung quanh cho những người đã từng lập trình như thế này, nhưng thay vì tăng giá trị, nó chỉ đơn giản đặt nó trueđể ngăn chặn những thứ như thế này.

Lưu ý rằng operator++(bool)không được chấp nhận.

http://www.open-std.org/jtc1/sc22/wg21/docs/ con / 2013 / n3797.pdf

Phụ lục D của C ++ 14:

D.1 Toán tử tăng dần với toán hạng bool
Việc sử dụng toán hạng loại bool với toán tử ++ không được dùng nữa (xem 5.3.2 và 5.2.6).


Trong khi điều đó sẽ giải thích lý do tại sao nó không được chấp nhận, nó không giải thích tại sao nó tồn tại ở nơi đầu tiên.

Nó tồn tại bởi vì có một số người đã đặt giá trị boolean bằng cách tăng nó khi lập trình trong C. C ++ được thiết kế để dễ dàng chuyển đổi từ C, vì vậy họ đã hỗ trợ boolloại này. Tôi chỉ cố gắng đưa ra một ví dụ lịch sử về thời điểm mọi người thực sự lập trình theo cách này.
David Stone
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.