C's stdbool.h adds a #define for the type _Bool to bool.
I know a #define was used instead of a typedef to allow #undef-ing for legacy code clashes. But why wasn't bool_t (to match the other standard types) used in place of bool? Is the _t used for typedef types only?
I ask because the platform I am working on adds a typedef for bool_t to _Bool.
EDIT: It's been correctly pointed out that the following is probably opinion based so consider it as only my reason for the primary question above.
So I'm wondering should I use that or continue to use bool? I kind of like the way the former makes the boolean standard type form match the other standard types.
C introduced the bool macro (that expands to _Bool) with the C99 Standard. They probably chose the name bool instead of bool_t because C++ in 1998 named their boolean type bool. In C++98 all integral types (except wchar_t already in C90) don't use a _t suffix.
I think you just found that the standard is inconsistent. bool is not the only type whose name does not have the _t suffix. Consider, for example, <setjmp.h>. It defines jmp_buf which is clearly a typedef yet does not end in _t.
I think the main reason why it's not bool_t is to make it look like it belongs to the family of standard types, int etc. However, they couldn't name the type bool due to compatibility purposes so hence the _Bool.
As for whether you should use bool or bool_t I think the question is rather opinion-based and cannot be answered just by using facts. However, I recommend you select one or the other and document that decision well in your coding guidelines.
Related
Any time I had the need of a Boolean type I was told to either create one, or better yet, use stdbool.h.
Since stdbool.h uses typedef bool _Bool, is there a reason to use the header instead just using type _Bool? Is it just for the additional macros (/* #define true 1 #define false 0 */)?
The obvious type to add into the language was bool. But unfortunately, plenty of code was written that included bool in other shapes and forms. Recall that support for a boolean type was added only in C99.
So the C language committee had no choice but to pull out a reserved identifier for it (_Bool). But, since the obvious choice of type name is still the same, stdbool.h was added to allow users the obvious name. That way, if your code didn't have a home-brewed bool, you could use the built in one.
So do indeed use stdbool.h if you aren't bound to some existing home-brewed bool. It will be the standard type, with all the benefits that type brings in.
The common practice has always been to use bool but when the type was officially introduced into the standard in C99, they didn't want to break the "roll-your-own" implementations. So they made the type _Bool as kind of a hack around the unofficial bools. Now there's no type name collision. Anyway, point is, use bool unless a legacy codebase breaks.
They are same. bool is an alias for _Bool.
Before C99 we used we dont have this type. (Earlier the use was limited to an integer tyoe with 0 as false and 1 as true).
You may not use it. Even you can undef bool (but it is recommended not to do so). But including it (stdbool.h and bool alias of _Bool) is good because then if someday it becomes reserved your code complies to that.1
1. You can use bool other way but it is better not to. Because in general when this stdbool.h is introduced it bears the plan of gradually making it standard and then even more stricter rule applies where we can't use bool as something other and it will be reserved as keyword.
I am in the early stages of framing stuff out on a new project.
I defined a function with a return type of "bool"
I got this output from PC-Lint
Including file sockets.h (hdr)
bool sock_close(uint8_t socket_id);
^
"LINT: sockets.h (52, 1) Note 970: Use of modifier or type '_Bool' outside of a typedef [MISRA 2012 Directive 4.6, advisory]"
I went ahead and defined this in another header to shut lint up:
typedef bool bool_t;
Then I started wondering why I had to do that and why it changed anything. I turned to MISRA 2012 Dir 4.6. It is concerned mostly about the width of primitive types like short, int, and long, their width, and how they are signed.
The standard does not give any amplification, rational, exception, or example for bool.
bool is explicitly defined as _Bool in stdbool.h in C99. So does this criteria really apply bool?
I thought _Bool was explicitly always the "smallest standard unsigned integer type large enough to store the values 0 and 1" according to section 6.2.5 of C99. So we know bool is unsigned. Is it then just a matter of the fact that _Bool is not fixed width and subject being promoted somehow that's the issue? Because the rational would seem to contradict that notion.
Adherence to this guideline does not guarantee portability because the size of the int type may determine whether or not an expression is subject to integer promotion.
How does just putting typedef bool bool_t; change anything - because I do nothing to indicate the width or the signdedness in doing so? The width of bool_t will just be platform dependent too. Is there a better way to redefine bool?
A type must not be defined with a specific length unless the implemented type is actually of that length
so typedef bool bool8_t; should be totally illegal.
Is Gimpel wrong in their interpretation of Directive 4.6 or are they spot on?
Use of modifier or type '_Bool' outside of a typedef [MISRA 2012 Directive 4.6, advisory]
That's nonsense, directive 4.6 is only concerned about using the types in stdint.h rather than int, short etc. The directive is about the basic numerical types. bool has nothing to do with that directive whatsoever, as it is not a numerical type.
For reasons unknown, MISRA-C:2012 examples use a weird type called bool_t, which isn't standard. But MISRA does by no means enforce this type to be used anywhere, particularly they do not enforce it in directive 4.6, which doesn't even mention booleans. MISRA does not discourage the use of bool or _Bool anywhere.
Is Gimpel wrong in their interpretation of Directive 4.6
Yes, their tool is giving incorrect diagnostics.
In addition, you may have to configure the tool (if possible) to tell it which bool type that is used. 5.3.2 mentions that you might have to do so if not using _Bool, implying that all static analysers must understand _Bool. But even if the bool type is correctly configured, dir 4.6 has nothing to do with it.
A potential concern with Boolean types is that a lot of code prior to C99 used a single-byte type to hold true/false values, and a fair amount of it may have used the name "bool". Attempting to store any multiple of 256 into most such types would be regarded as storing zero, while storing a non-zero multiple of 256 into a c99 "bool" would yield 1. If a piece of code which uses a C99 "bool" is ported into a piece of code that uses a typedef'ed byte, the resulting code could very easily malfunction (it's somewhat less likely that code written for a typedef'ed byte would rely upon any particular behavior when storing a value other than 0 or 1).
I keep stumbling across new types in C. Most recently, I spent a long time trying to get a size_t variable to accept the output of getline() (misled, perhaps, by this) only to eventually notice that ssize_t (yes, two s's) is the correct type. Is there a list of all the possible variable declarations somewhere?
Well, not perhaps as such, but if you know which function to call (getline() in your case) then the manual page for that function of course will specify the proper types.
There aren't that many in the standard library, at least not which are commonly used.
In C it is possible to define your own type names using typedef. Example:
typedef int myowntype;
For this the possible type names depend on which header files you have included. Thus you have to consult the documentation for each library you use.
In the standard library there are only a few type names, time_t, size_t for example.
As noted in the comments it is also possible to declare your own types using struct for example. One can then define a type name for a new type:
typedef struct {
int a;
int b;
} my_type;
defines a new type struct {int a; int b;} and defines a new type name my_type for this struct type. The struct by itselves can also define a type name written with the struct in it's name:
struct my_struct {
int a;
int b;
}
defines a new type and a type name struct my_struct that can be used to declare variables:
struct my_struct a;
There is no list of all possible types in C, because there are postentially infinitely many of them (or close enough to infinitely many).
I suggest you're approaching this from the wrong direction. Knowing all possible types wouldn't be very helpful in programming; what you need to know is which type to use for a given purpose.
For any function you want to call (including getline) the first thing you need to do is to read the documentation for that function.
There are relatively few types defined by the language. There are built-in types like char, int, double, and so forth, and there are a number of types defined by the standard library. Consult any decent C reference, or the C standard itself. The latest draft is N1570. (This is a draft of the 2011 ISO C standard, which is not yet fully implemented.)
More types are defined by secondary standards. POSIX is probably the most notable of these. For example, ssize_t (which is the signed type corresponding to size_t) is defined by POSIX, not by ISO C.
Be sure to read the documentation to find out just what characteristics are guaranteed for a given type. For example, size_t is guaranteed to be an unsigned integer type, and time_t is guaranteed to be an arithmetic type (it could be signed, unsigned, or even floating-point). If you want to write portable code, don't make any assumptions beyond what's guaranteed.
What is the reasoning behind types to be redefined in GLib? Why do they turn char into gchar, int into gint, etc.?
Check out Basic Types in the GLib documentation. Essentially, it's to guarantee that certain types will exist with certain semantics, regardless of which C compiler or platform you're using. The types that C guarantees anyway are typedefed just to make all of the type names look uniform.
See also this answer.
Essentially, it's because glib's standard-width types such as guint32 predate the C99 and later standard-width types, such as uint32_t, which now exists (as of C99 and later) and is exactly equivalent.
So, glib's g-prefixed types are now essentially obsolete. Use the standardized fixed-width types like uint32_t now instead.
This seems like a simple question, but I can't find it with the Stack Overflow search or Google. What does a type followed by a _t mean? Such as
int_t anInt;
I see it a lot in C code meant to deal closely with hardware—I can't help but think that they're related.
As Douglas Mayle noted, it basically denotes a type name. Consequently, you would be ill-advised to end variable or function names with '_t' since it could cause some confusion. As well as size_t, the C89 standard defines wchar_t, off_t, ptrdiff_t, and probably some others I've forgotten. The C99 standard defines a lot of extra types, such as uintptr_t, intmax_t, int8_t, uint_least16_t, uint_fast32_t, and so on. These new types are formally defined in <stdint.h> but most often you will use <inttypes.h> which (unusually for standard C headers) includes <stdint.h>. It (<inttypes.h>) also defines macros for use with the printf() and scanf().
As Matt Curtis noted, there is no significance to the compiler in the suffix; it is a human-oriented convention.
However, you should also note that POSIX defines a lot of extra type names ending in '_t', and reserves the suffix for the implementation. That means that if you are working on POSIX-related systems, defining your own type names with the convention is ill-advised. The system I work on has done it (for more than 20 years); we regularly get tripped up by systems defining types with the same name as we define.
The _t usually wraps an opaque type definition.
GCC merely add names that end with _t to the reserved namespace you may not use, to avoid conflicts with future versions of Standard C and POSIX (GNU C library manual). After some research, I finally found the correct reference inside the POSIX Standard 1003.1: B.2.12 Data Types (Volume: Rationale, Appendix: B. Rationale for System Interfaces, Chapter: B.2 General Information):
B.2.12 Data Types
Defined Types
The requirement that additional types defined in this section end in "_t" was prompted by the problem of name space pollution. It is difficult to define a type (where that type is not one defined by POSIX.1-2017) in one header file and use it in another without adding symbols to the name space of the program. To allow implementors to provide their own types, all conforming applications are required to avoid symbols ending in "_t", which permits the implementor to provide additional types. Because a major use of types is in the definition of structure members, which can (and in many cases must) be added to the structures defined in POSIX.1-2017, the need for additional types is compelling.
In a nutshell, the Standard says that there are good chances of extending the Standard types' list, therefore the Standard restricts the _t namespace for its own use.
For instance, your program matches POSIX 1003.1 Issue 7 and you defined a type foo_t. POSIX 1003.1 Issue 8 is eventually released with a newly defined type foo_t. Your program does not match the new version, which might be a problem. Restricting the _t usage prevents from refactoring the code. Thus, if you aim to a POSIX compliancy, you should definitely avoid the _t as the Standard states it.
Side note: personally, I try to stick to POSIX because I think it gives good basics for clean programming. Moreover, I am pretty fond of Linux Coding Style (chapter 5) guidelines. There are some good reasons why not using typedef. Hope this help!
It's a convention used for naming data types, e.g with typedef:
typedef struct {
char* model;
int year;
...
} car_t;
It is a standard naming convention for data types, usually defined by typedefs. A lot of C code that deals with hardware registers uses C99-defined standard names for signed and unsigned fixed-size data types. As a convention, these names are in a standard header file (stdint.h), and end with _t.
The _t does not inherently have any special meaning. But it has fallen into common use to add the _t suffix to typedef's.
You may be more familiar with common C practices for variable naming... This is similar to how it's common to stick a p at the front for a pointer, and to use an underscore in front of global variables (this is a bit less common), and to use the variable names i, j, and k for temporary loop variables.
In code where word-size and ordering is important, it's very common to use custom defined types that are explicit, such as BYTE WORD (normally 16-bit) DWORD (32-bits).
int_t is not so good, because the definition of int varies between platforms -- so whose int are you conforming to? (Although, these days, most PC-centric development treats it as 32 bits, much stuff for non-PC development still treat int's as 16 bits).
It's just a convention which means "type". It means nothing special to the compiler.
It means type. size_t is the size type.
There were a few good explanations about the subject. Just to add another reason for re-defining the types:
In many embedded projects, all types are redefined to correctly state the given sizing to the types and to improve portability across different platforms (i.e hardware types compilers).
Another reason will be to make your code portable across different OSs and to avoid collisions with existing types in the OS that you are integrating in your code. For this, usually a unique (as possible) prefix is added.
Example:
typedef unsigned long dc_uint32_t;
If you're dealing with hardware interface code, the author of the code you're looking at might have defined int_t to be a specific size integer. The C standard doesn't assign a specific size to the int type (it depends on your compiler and target platform, potentially), and using a specific int_t type would avoid that portability problem.
This is a particularly important consideration for hardware interface code, which may be why you've first noticed the convention there.
For example in C99, /usr/include/stdint.h:
typedef unsigned char uint8_t;
typedef unsigned short int uint16_t;
#ifndef __uint32_t_defined
typedef unsigned int uint32_t;
# define __uint32_t_defined
#endif
#if __WORDSIZE == 64
typedef unsigned long int uint64_t;
#else
__extension__
typedef unsigned long long int uint64_t;
#endif
_t always means defined by typedef.