Why does __uint8_t exist? - c

To better understand how libc works, I was reading the FreeBSD source code. And there I stumbled upon the definition of __uint8_t in the sys/_types.h file. I can understand definitions of types like u_int8_t for compatibility with old code, but a special _types.h file where all types start with __? Why are these types defined in the _types.h file that accompanies types.h and not just types.h altogheter with other types like standard uint8_t?
(I assume that these types with __ at the beginning are not defined to be compatible with the old code because it is not written in the comment)

Why does __uint8_t exist?
To provide access to the implementation's 8-bit unsigned type that does not collide with user code.
a special _types.h file where all types start with __
__ names are reserved by the implementation, so using that name will not collide with user code.
Why are these types defined in the _types.h file that accompanies types.h and not just types.h altogether with other types like standard uint8_t?
So the implementation can include its include its own files without including the various STD C .h files.
uint8_t is defiifned in <stdint.h>. Defining __xxx_t in there too would bring in definitions other definitions that may conflict with user code. Compliant user code is not required to include <stdint.h>.

Related

An external struct declaration, but the struct definition is just above

I double-checked all the similar questions here, I really hope not to duplicate.
I am intrigued by the the following extract from stdio.h:
typedef struct _iobuf {
/* Members here omitted ... */
} FILE;
extern FILE _iob[20];
We define a new type named FILE by using the struct syntax. Just after that, we declare an extern variable _iob of type FILE. Therefore, this variable must come from another place.
But, since the definition of FILE is in this file, how can it be possible? I see two possibilities only.
The first is to have something like:
#include <stdio.h>
FILE _iob[20] = /* definition */
The second is to have another source file where the struct is copy-pasted and the variable declared, I guess a very bad practice that we can omit.
Since I am a self-learner, I would be very happy to receive a confirm of my understanding.Thanks!
Either:
somewhere in the library source code files, there is text as you describe, an inclusion of <stdio.h> followed by a definition of FILE _iob[20], or
somewhere in the library source code files, there is a definition of _iob written in a programming language other than standard C.
The latter may be assembly language, non-standard C with extensions, or something else. An implementation of C is not required to use only C source code to define itself.
In general, it is good practice for the source file that defines an object to also include its own header. A primary purpose of a header file is to tell other source files about things defined in the associated source file. But including the header file in the source file serves another purpose: The compiler will see both the declarations in the header and the definitions in the source file and will issue error messages if they are incompatible. So this provides a check that catches typos or other errors when building the library.

Reference of all functions and constants in stdlib.h, stdio.h?

I'd like to look up all the functions, constants and types defined in C libraries: stdlib.h, stdio.h, ctype.h etc. So, when in C program I do: #include <stdlib.h> or #include <stdio.h> I'd like to know what are all the functions, constants and types I get with that?
What's the easiest way to do this locally on the computer? I'm not so much interested in online references, especially if they're not official.
Is there a manpage that lists this for eg stdlib? Does maybe GNU info program have docs for this? Or do I have to find an actual header file and look it up?
I'd prefer an universal approach, but if it differs from system to system I'm curious how to do that on both Mac and Linux?
When you include one of the standard C headers, at least three types of identifiers may be declared:
Identifiers specified by the C standard. The authoritative source for information on these is the C standard, plus documentation for the C implementation you are using.
Identifiers for extensions to the C language. For example, the headers may declare identifiers for POSIX functions. The headers might declare such identifiers only if you have requested them by defining certain preprocessor symbols before including the headers.
Identifiers for internal use of the C implementation. These identifiers commonly begin with an underscore followed by another underscore or a caputal letter, as the C standard reserves those. You can discover these identifiers by examining the actual header files in your C implementation, but you should not use them unless documentation for your implementation offers them for use.
Overall, if you want to know what C provides in the standard headers, you should read either the C standard (for authoritative information) or a good C textbook (for tutorial information). If you want to know what else is in the headers, there is a large variety of things that an implementation could put into the headers, so the way to find out what is there is to read the documentation for the implementation and/or to examine the header file and then find the documentation for the extra things it provides, such as the POSIX documentation.
You asked for sources on your computer. Your C implementation may come with documentation, and Unix includes documentation accessible via the man command. While you can examine the actual header files, it is important to understand the current contents of the headers do not constitute any promise about future behavior. Any internal identifiers may change in future versions, and the behavior of standard identifiers may change as permitted by the C standard.
Your terminology stdlib is not well-defined. There's a "Standard I/O Library" as part of the C Programming Language, and a stdlib.h header file.
For C identifiers, here's an overview for ISO C and POSIX identifiers.
Apart from that, you can look at the symbols in library files with
nm -AP /path/to/libfoobar.a
Update
To inspect a header in the form the compiler sees it, look at the result of preprocessing (-E):
$ gcc -E /usr/include/stdlib.h|less
typedef unsigned char __u_char;
typedef unsigned short int __u_short;
typedef unsigned int __u_int;
typedef unsigned long int __u_long;
[...]
typedef struct
{
int quot;
int rem;
} div_t;
typedef struct
{
long int quot;
long int rem;
} ldiv_t;
[...]
extern long int random (void) __attribute__ ((__nothrow__ , __leaf__));
[...]

Where do I find those types in .h file

In a .h file there's no includes of other .h files
then I see uint8_t, int16_t, spin lock_t, atomic_t, ssize_t,_be32, _be16,
the primitives like char, unsigned long, struct are understood by compilers, but what about those one ends with _t? where are they defined?
I check linux/kernel.h, i don't see them also.
For Linux kernel and Linux kernel modules, they are all defined in:
/usr/src/linux/include/linux/types.h

Best practice: Use of stdint types in a header file

What's the best way to ensure that stdint.h is included for headers that use the types from that header?
The alternatives I can see are:
including stdint.h in the header itself (dangerous, is it not?)
flagging something to the compiler if it's not included when parsing the header (something like #ifndef _STDINT_H with an accompanying #error "stdint.h not included"
Educating the other developer in always including stdint.h before any of my headers that require it, either using comments, conversation, documentation or a mixture of all three (the last one being preferable).
If there are any other alternatives worth mentioning, feel free to do so - I'm just guessing at what I should do here.
If you use types from stdint.h in your header, you really should include stdint.h in that header.
It is generally preferred to include the least amount of files from a header to reduce compile time. Therefore, whenever possible, you should forward declare types in headers. Since the types from stdint.h cannot be forward declared (they're just typedefs of primitive types), there is no other option than including stdint.h in the header.
I my oppinion, including header files in header files is ok if you use include guards.
Something like
# ifndef HEADER
# define HEADER
# include header.h
# endif

Compile time checking existence of stdint.h

I'm working with legacy embedded C code which defines the types uint8_t, uint16_t and uint32_t in a header file using the typedef keyword.
For discussion, let us say the file typedefs.h contains these definitions.
In my new C source module, I include stdint.h. I also include other header files which include typedefs.h somewhere in the hierarchy. As expected, the compiler complains about multiple defined symbols.
I would like to modify the legacy file typedefs.h so that it only declares the uint*_t types if either stdint.h is not included or better if the uint*_t types are not defined.
My understanding is that #ifndef cannot be used since typedef is not a preprocessor directive.
So how do I tell the compiler to not define the uint*_t if they already exist (or if the stdint.h is already included)?
Note: this would be easy if the C specification defined standard include guard definitions for the header files.
FWIW, I am using Green Hills compiler, 4.24, for an ARM9 processor.
I beleive that the stdint.h should also be defining a macro for the limits of the types that it defines. You should be able to test for those using a #ifdef and the like.
#ifndef UINT32_MAX
typdef ... uint32_t;
#define UINT32_MAX ...
...
#endif
Edit: Originally used UINT32_MIN, but as Jens Gustedt poited out this is the one combination of signed/unsigned and min/max that doesn't occur.
Just fix the legacy header to always include stdint.h to get these types, remove the duplicate definitions, and provide a drop-in file stdint.h for broken systems that lack it.
If you're on a UNIX system, then you should back-up a step and use a configuration package like autoconf(1) or automake(1). It's designed to handle problems like this.

Resources