Là bool một loại C bản địa?


265

Tôi đã nhận thấy rằng mã nhân Linux sử dụng bool, nhưng tôi nghĩ rằng bool là loại C ++. Bool là phần mở rộng C tiêu chuẩn (ví dụ: ISO C90) hoặc phần mở rộng GCC?


2
Phần 9 của câu hỏi thường gặp comp.lang.c thảo luận về điều này.
Keith Thompson

1
Liên kết trực tiếp: c-faq.com/bool/index.html
Ellen Spertus

Nhân Linux sử dụng -std=gnu89hỗ trợ _Boolnhư một phần mở rộng cho C90. "bao gồm / linux / type.h" có typedef _Bool bool;.
Ian Abbott

Ngoài ra, FWIW, nhân Linux 2.6.19 là phiên bản đầu tiên sử dụng typedef _Bool bool;(cam kết 6e21828743247270d09a86756a0c11702500dbfb ) và nó yêu cầu GNU C 3.2 trở lên.
Ian Abbott

Câu trả lời:


368

bool tồn tại trong C - C99 hiện tại, nhưng không tồn tại trong C89 / 90.

Trong C99, kiểu bản địa thực sự được gọi _Bool, trong khi đó boollà một macro thư viện tiêu chuẩn được xác định trong stdbool.h(dự kiến ​​sẽ giải quyết _Bool). Các đối tượng kiểu _Boolgiữ 0 hoặc 1, trong khi truefalsecũng là macro từ stdbool.h.

Lưu ý, BTW, điều này ngụ ý rằng bộ tiền xử lý C sẽ diễn giải #if truenhư #if 0trừ khi stdbool.hđược bao gồm. Trong khi đó, bộ tiền xử lý C ++ được yêu cầu để nhận biết nguyên bản truelà một ngôn ngữ.


62
Có một tiêu chuẩn ISO C mới, được công bố vào năm 2011 (sau khi câu trả lời này được đăng). ANSI, như thường lệ, đã áp dụng tiêu chuẩn ISO C11 làm tiêu chuẩn ANSI. Vì các lý do lịch sử, cụm từ "ANSI C" thường (nhưng không chính xác) đề cập đến ngôn ngữ được xác định theo tiêu chuẩn ANSI C89 / ISO C90. Do các tiêu chuẩn C hiện được ISO công bố đầu tiên và vì đã có ba tiêu chuẩn ISO C, với các mức độ áp dụng khác nhau, tốt nhất nên tham khảo năm tiêu chuẩn được công bố (ISO C90, ISO C99, ISO C11) để tránh bất kỳ lú lẫn.
Keith Thompson

8
Điều này có nghĩa là _Boolchiếm 1 bit bộ nhớ?
Geremia

27
@Geremia: Không. Tại sao? Trong C, mỗi đối tượng có thể định địa chỉ phải chiếm ít nhất 1 byte. Và trong thực tế cuộc sống thực _Boolthường mất 1 byte bộ nhớ. Tuy nhiên, đặc tả ngôn ngữ cho phép sử dụng rõ ràng _Boolnhư loại trường bit, nghĩa là bằng cách sử dụng các trường bit, bạn có thể ép một _Boolgiá trị thành một bit (bên trong cấu trúc lớn hơn).
AnT

@AnT Làm thế nào một _Boolgiá trị có thể được đánh địa chỉ trực tiếp (nghĩa là có kích thước 1 byte) và cũng có thể tham gia vào một trường bit? Một mảng _Boolvẫn sẽ yêu cầu tất cả các yếu tố của nó phải có địa chỉ (ví dụ _Bool* ptr = &boolArray[123]).
Đại

118

C99 đã thêm một _Boolkiểu dữ liệu dựng sẵn (xem Wikipedia để biết chi tiết) và nếu bạn #include <stdbool.h>, nó cung cấp booldưới dạng macro _Bool.

Bạn đã hỏi về nhân Linux nói riêng. Nó giả định sự hiện diện của _Boolvà cung cấp một booltypedef chính nó trong bao gồm / linux / types.h .


26
Về lý do tại sao, nó cho phép nó không được xác định và xác định lại trong đó định nghĩa của nó có thể gây ra xung đột với mã kế thừa.
Clifford

32

Không, không có booltrong ISO C90.

Dưới đây là danh sách các từ khóa trong tiêu chuẩn C (không phải C99):

  • auto
  • break
  • case
  • char
  • const
  • continue
  • default
  • do
  • double
  • else
  • enum
  • extern
  • float
  • for
  • goto
  • if
  • int
  • long
  • register
  • return
  • short
  • signed
  • static
  • struct
  • switch
  • typedef
  • union
  • unsigned
  • void
  • volatile
  • while

Đây là một bài viết thảo luận về một số khác biệt khác với C như được sử dụng trong kernel và tiêu chuẩn: http://www.ibm.com/developerworks/linux/l Library / l-gcc-hacks / index.html


6
Đối với các mục đích thực tế, nó có thực sự quan trọng miễn là vẫn không có hỗ trợ trình biên dịch phong nha? Ngay cả gcc cũng không có một nửa tính năng C99 cho đến gần đây và MSVC không có hầu hết các tính năng đó và có lẽ sẽ không bao giờ ...
Pavel Minaev

5
@Jonathan Leffler, người hỏi đặc biệt hỏi về ISO C90. :) Trong thực tế, thông thường khi mọi người nhắc đến ANSI C, họ có nghĩa là C90. Tôi không sử dụng hoặc thực sự có kế hoạch sử dụng C99 và tôi nghĩ nhiều người cũng cảm thấy như vậy.
BobbyShaftoe

6
@BulkShaftoe: Người đăng ban đầu nói rõ ràng trong một bình luận rằng C90 là một ví dụ.
Keith Thompson

32

C99 có nó trong stdbool.h , nhưng trong C90, nó phải được định nghĩa là typedef hoặc enum:

typedef int bool;
#define TRUE  1
#define FALSE 0

bool f = FALSE;
if (f) { ... }

Cách khác:

typedef enum { FALSE, TRUE } boolean;

boolean b = FALSE;
if (b) { ... }

5
Lưu ý rằng hành vi của typedef sẽ khác với hành vi của C99 boolvà cũng khác với hành vi của nhiều trình biên dịch bit. Ví dụ: bool x=4294967296LL;hoặc bool x=0.1;sẽ được đặt xthành một trên C99, nhưng có thể sẽ đặt hầu hết các phiên bản typedef thành 0.
supercat

17
/* Many years ago, when the earth was still cooling, we used this: */

typedef enum
{
    false = ( 1 == 0 ),
    true = ( ! false )
} bool;

/* It has always worked for me. */

16
Các giá trị ban đầu là hoàn toàn không cần thiết. typedef enum { false, true };cũng tốt Nếu bạn khăng khăng đòi nói rõ ràng hơn, bạn có thể viết typedef enum { false = 0, true = 1 };. (Hoặc chỉ #include <stdbool.h>khi trình biên dịch của bạn hỗ trợ nó; nó đã được chuẩn trong 14 năm.)
Keith Thompson

9
@KeithThndry Các giá trị ban đầu có thể không cần thiết, nhưng câu trả lời này chọn chúng theo cách rất tao nhã, không phải với các giá trị tùy ý, mà sử dụng ngữ nghĩa riêng của ngôn ngữ và để trình biên dịch quyết định.
MestreLion 16/2/2015

11
@MestreLion: Đảm bảo ngữ nghĩa của ngôn ngữ typedef enum { false, true } bool;hoạt động chính xác như mong đợi. 1 == 0! falsekhông thanh lịch, họ chỉ đơn thuần là bị xáo trộn. Không có quyết định cho trình biên dịch để thực hiện; nó phải tuân theo ngữ nghĩa được xác định bởi ngôn ngữ.
Keith Thompson

11
@KeithThndry: Tôi không nghĩ họ bị xáo trộn, tôi đoán ý định của tác giả là chọn các giá trị "tự nhiên" nhất: falseđược đặt thành bất kỳ giá trị nào mà ngôn ngữ nói nên đánh giá sự bất bình đẳng và truengược lại với "ngược" ( một lần nữa, bất kể đó là gì). Theo cách này, người ta không nên quan tâm nếu đó là {1, 0}, {-1, 0}, {0, 1}, v.v. và nó được đảm bảo hoạt động trong các so sánh, bởi vì nó được chế tạo bằng cách sử dụng một.
MestreLion 16/2/2015

3
@MestreLion: Bất cứ ai biết C đều biết các giá trị số của falsetrue. Bất cứ ai không biết C không phải là đối tượng mong đợi cho mã C. Và như tôi đã nói, C đã có kiểu Boolean tích hợp từ thiên niên kỷ trước.
Keith Thompson

12

_Boollà một từ khóa trong C99: nó chỉ định một loại, giống như inthoặc double.

6.5.2

2 Một đối tượng được khai báo là kiểu _Bool đủ lớn để lưu trữ các giá trị 0 và 1.


6

C99 định nghĩa bool, truefalsetrong stdbool.h.



1

stdbool.h định nghĩa các macro đúng và sai, nhưng hãy nhớ nó được xác định là 1 và 0.

Đó là lý do tại sao sizeof(true)là 4.


0

Không có điều đó, có lẽ chỉ là một macro cho int


Thật tuyệt với -1 ... câu hỏi là C90, không phải 99 tôi tin
sindre j

5
Vâng, ông nói tiêu chuẩn C, ví dụ C90, tôi giả sử bao gồm C99.
Matt Joiner

2
Anh ấy đề cập đến C90 một cách đặc biệt, KHÔNG phải C99, vì vậy tôi cho rằng ý anh ấy là gì. Theo wikipedia trình biên dịch duy nhất hỗ trợ đầy đủ C99 là Sun Studio từ Sun microsystems. Bây giờ, đó là một tiêu chuẩn được chấp nhận rộng rãi phải không? Có thể cho rằng hầu hết các trình biên dịch hiện đại đều thực hiện các phần của tiêu chuẩn C99, tôi có lẽ nên đề cập đến điều đó để tránh những bình luận ngu ngốc như của bạn! Java hoặc c # để làm gì với btw này?
sindre j

8
tiện ích mở rộng C tiêu chuẩn (ví dụ: ISO C90) đang phân loại loại tiêu chuẩn C mà anh ta quan tâm, không phải riêng C90. một câu trả lời thích hợp cho điều này là, một C chuẩn như C90, đặc biệt là tiêu chuẩn C99, không thực hiện một boolkiểu.
Matt Tham gia

0

C99 đã thêm một boolloại có ngữ nghĩa khác về cơ bản so với tất cả các loại số nguyên đã tồn tại trước đó trong C, bao gồm các loại mở rộng do người dùng xác định và trình biên dịch dành cho các mục đích đó và một số chương trình có thể có "type-def" ed để bool.

Ví dụ, đã cho bool a = 0.1, b=2, c=255, d=256;, boolloại C99 sẽ đặt cả bốn đối tượng thành 1. Nếu sử dụng chương trình C89 typedef unsigned char bool, các đối tượng sẽ nhận được 0, 1, 255 và 0 tương ứng. Nếu được sử dụng char, các giá trị có thể như trên hoặc ccó thể là -1. Nếu nó đã sử dụng phần mở rộng trình biên dịch bithoặc __bitloại, kết quả có thể sẽ là 0, 0, 1, 0 (xử lý bittheo cách tương đương với trường bit không dấu có kích thước 1 hoặc loại số nguyên không dấu với một bit giá trị).

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.