Standard alternative to POSIX typedef - c

Before I read that POSIX reserved the typedefs ending in _t I used it frequently. What would be a good commonly-used standard alternative for this suffix?

"Standard" is a big word. If you refer to the ISO C, it's beyond its job to define that; indeed, it does use names like time_t or size_t because it's allowed to as POSIX is secondary to it. Moreover, this convention does not apply to Windows-based programming environments, for instance.
IMHO, it's not really needed to state that a type is a type. C has a limited number of types so it's elementary to determine whether it's a built-in type or an ADT. Also, such built-in types have lower case one word names: if you saw stat_buffer you would immediately know it may not be a built-in type.
Whatever choice you make it's important to keep it consistent across your source code. Anyways, very frequent choices I see may be:
Uppercase nomenclature, like Time or Pid
_type suffix, like time_type or pid_type
Invisible suffix, like time or pid

Related

Can _Generic match on string of type?

Example use-case, do a thing for all types that contain the string "int". More precise, have a struct Point in different versions as Point__alloca or Point__boehm, and then a macro new that switches on that name. Hm, maybe macro stringification could do that?
Standard C supports only very limited introspection (examination of the program by itself) and nothing that would discern whether a type name contained particular characters or any ability to enumerate “all types” at all, let alone all types matching a criterion. In short, there is no support for the feature you request.

C compiler - list __builtin_ types

here is a small (and working) C code:
typedef __builtin_va_list __va_list;
int main() {
return 0;
}
I found an answer, how gcc found the base type:
Pycparser not working on preprocessed code
But how can I list all of the __builtin_ "base" types, which not defined explicitly?
Thanks,
a.
how can I list all of the __builtin_ "base" types, which not defined explicitly?
TL;DR: there is no general-purpose way to do it.
The standard does not define any such types, so they can only be implementation-specific. In particular, C does not attribute any significance to the __builtin_ name prefix (though such identifiers are reserved), nor does it acknowledge that any types exist that are not derived from those it does define. Thus, for most purposes, the types you are asking about should be considered an implementation detail.
If there were a way to list implementation-specific built-in types, it would necessarily be implementation-specific itself. For example, you might be able to find a list such as you are after in the compiler's documentation. You could surely derive one from the compiler's own source code, if that's available to you. You could maybe extract strings from the compiler binary, and filter for a characteristic name pattern, such as strings starting with "__builtin_".
You could also consider parsing all the standard library headers (with the assumption that they are correct) to find undeclared types, though that's not guaranteed to find all the available types. Moreover, with some systems, for example GNU's, the C standard library (to which the headers belong) is separate from the compiler.

Good OO naming scheme for c

I find myself with a lot of functions that are oo style in c(nothing with fancy macros or function pointers just struct + functions that take that struct type as a first argument.
Is my_func_my_type a good scheme for such things? If I use that should I try to be consistent? what if it one of my functions name becomes > 20 characters? > 25? Should I keep the style consistent even then?
Also what is a good naming scheme for constructors/initializers/destructors?
Is there something beter then new_my_type , init_my_type, free_my_type ?
P.S. Is there a good name for this/self ptr or should I just name the first parameter of OO like function as I would in a normal function (to_init, some_guy,ect.)
I would personally use a scheme consistent with most C libraries that put the library name as a prefix of the function. Which would give for instance void MyObject_MyFunction. For construction/destruction, you can stay consistent and use MyObject_Construct, MyObject_Destroy. I'd say the name don't matter much as long as you stay consistent.
'good' is a bit subjective, but I find it the easiest to maintain to choose a certain scheme (incorporating struct name into method) and follow it strictly. Really long function names I tend to avoid though, if a function is so complicated that it need such a long name it's probably time to refactor it, split into subfunctions etc.
I also do not use underscores, but that's a matter of taste.
A sample of what's used here:
typedef struct Discriminator
{
//members
} Discriminator;
DiscriminatorConstruct( Discriminator* p );
DiscriminatorDestruct( Discriminator* p );
DiscriminatorFunctionA( Discriminator* p, int arg1, int arg2 );
For lack of one within the C world, C++ provides a useful precedent in the naming of its functions:
[[namespace::...]struct::]function
There's nothing like namespaces in C, but you can just think of and model them as prefixes shared by related structs. For readability, it helps to have something to visually separate the distinct naming components. If you like using underscores in your functions, you might consider two underscores as a separator, otherwise perhaps one. (Technically, two underscores may be reserved for the implementation, but I've never seen any implementation identifier that wasn't prefixed with underscores put a double underscore internally).
Keeping the names close to C++ also helps programmers span both languages, and in migrating code back and forth if necessary. Similarly, C++ terminology may be adopted: constructor, destructor, possibly new and delete (though these names may become misnomers if the C code is ported to C++ but continues to use free/malloc).
IMHO, consistent and clear naming saves more hassles than long identifiers cause, but if something becomes a pain then seek a localised workaround such as a macro, inline wrapper function, function pointer etc..

What style to use when naming types in C

According to this stack overflow answer, the "_t" postfix on type names is reserved in C. When using typedef to create a new opaque type, I'm used to having some sort of indication in the name that this is a type. Normally I would go with something like hashmap_t but now I need something else.
Is there any standard naming scheme for types in C? In other languages, using CapsCase like Hashmap is common, but a lot of C code I see doesn't use upper case at all. CapsCase works fairly nicely with a library prefix too, like XYHashmap.
So is there a common rule or standard for naming types in C?
Yes, POSIX reserves names ending _t if you include any of the POSIX headers, so you are advised to stay clear of those - in theory. I work on a project that has run afoul of such names two or three times over the last twenty or so years. You can minimize the risk of collision by using a corporate prefix (your company's TLA and an underscore, for example), or by using mixed case names (as well as the _t suffix); all the collisions I've seen have been short and all-lower case (dec_t, loc_t, ...).
Other than the system-provided (and system-reserved) _t suffix, there is no specific widely used convention. One of the mixed-case systems (camelCase or InitialCaps) works well. A systematic prefix works well too - the better libraries tend to be careful about these.
If you do decide to use lower-case and _t suffix, do make sure that you use long enough names and check diligently against the POSIX standard, the primary platforms you work on, and any you think you might work on to avoid unnecessary conflicts. The worst problems come when you release some name example_t to customers and then find there is a conflict on some new platform. Then you have to think about making customers change their code, which they are always reluctant to do. It is better to avoid the problem up front.
The Indian Hill style guidelines have some suggestions:
Individual projects will no doubt have
their own naming conventions. There
are some general rules however.
Names with leading and trailing underscores are reserved for system
purposes and should not be used for
any user-created names. Most systems
use them for names that the user
should not have to know. If you must
have your own private identifiers,
begin them with a letter or two
identifying the package to which they
belong.
#define constants should be in all CAPS.
Enum constants are Capitalized or in all CAPS
Function, typedef, and variable names, as well as struct, union, and
enum tag names should be in lower
case.
Many macro "functions" are in all CAPS. Some macros (such as getchar and
putchar) are in lower case since they
may also exist as functions.
Lower-case macro names are only
acceptable if the macros behave like a
function call, that is, they evaluate
their parameters exactly once and do
not assign values to named parameters.
Sometimes it is impossible to write a
macro that behaves like a function
even though the arguments are
evaluated exactly once.
Avoid names that differ only in case, like foo and Foo. Similarly,
avoid foobar and foo_bar. The
potential for confusion is
considerable.
Similarly, avoid names that look like each other. On many terminals and
printers, 'l', '1' and 'I' look quite
similar. A variable named 'l' is
particularly bad because it looks so
much like the constant '1'.
In general, global names (including
enums) should have a common prefix
identifying the module that they
belong with. Globals may alternatively
be grouped in a global structure.
Typedeffed names often have "_t"
appended to their name.
Avoid names that might conflict with
various standard library names. Some
systems will include more library code
than you want. Also, your program may
be extended someday.
C only reserves some uses of a _t suffix. As far as I can tell, this is only current identifiers ending with _t plus any identifier that starts int or uint (7.26.8). However, POSIX may reserve more.
It's a general problem in C, since you have extremely flat namespaces, and there's no silver bullet. If you're familiar with CapCase names and they work well for you, then you should continue to use them. Otherwise, you'll have to evaluate the goals of the current project and see which solution best meets them.
CapsCase is often used for types in C.
For instance, if you look at projects in the GNOME ecosystem (GTK+, GDK, GLib, GObject, Clutter, etc.), you'll see types like GtkButton or ClutterStageWindow. They only use CapsCase for data types; function names and variables are all lower-case with underscore separators - e.g. clutter_actor_get_geometry().
Type naming schemes are like indentation conventions - they generate religious wars with people asserting some sort of moral superiority for their preferred approach. It is certainly preferable to follow the style in existing code, or in related projects (e.g. for me, GNOME over the last few years.)
However, if you're starting from scratch and have no template, there's no hard-and-fast rule. If you're interested in coding efficiently and leaving work at reasonable hour so you can go home and have a beer or whatever, you certainly should pick a style and stick to it for your project, but it matters very little exactly which style you pick.
One alternate solution that works reasonably well is to use uppercase for all type names and macro names. Global variables may be CapCase (CamelBack) and all local variables lower case.
This technique helps to improve readability and also takes advantage of language syntax which reduces the number of pollution characters in variable names; e.g. gvar, kvar, type_t, etc. For example, data types cannot be syntatically confused with any other type.
Global variables are easily distinguished from locals by having at least one upper case letter.
I agree that prefixed or postfixed underscores should be avoided in all token names.
Lets look at the example below.
Its readily clear that InvertedCount is a global due to its case. It's equally clear that INT32U and RET_ERR are types due to their sytax. Its also clear that INVERT_VAL() is a macro due to the fact thats its on the right hand side and there is no cast so it cant be a data type.
One thing is for sure though. Whichever method you use, it should be inline with your organizations coding standard. For me, the least amount of clutter, the better.
Of course, style is a different issue.
#define INVERT_VAL(x) (~x)
#define CALIBRATED_VAL 100u
INT32U InvertedCount;
typedef enum {
ERR_NONE = 0,
...
} RET_ERR;
RET_ERR my_func (void)
{
INT32U val;
INT32U check_sum;
val = CALIBRATED_VAL; // --> Lower case local variable.
check_sum = INVERT_VAL(val); // --> Clear use of macris.
InvertedCount = checksum; // --> Upper case global variable.
// Looks different no g prefix required.
...
return (ERR_NONE);
}
There are many ideas and opinion on this subject, but there is no one universal standard for naming types. The most important thing is to be consistent. In the absence of coding standards, when maintaining code, resist the urge to use another naming convention. Introducing a new naming convention, even if it's perfect, can add unnecessary complexity.
This is actually a great topic to raise when interviewing people. I've never come across a good programmer that didn't have an opinion on this. No opinion or no passion in the answer indicates that the person isn't an experienced programmer.

What does a type followed by _t (underscore-t) represent?

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.

Resources