I read this official manual about GCC. Sometimes I have a a problem with translating of text. On the page number six (chapter 2.1) I can't understand such fragment of text:
The ISO C standard defines (in clause 4) two classes of conforming
implementation. A conforming hosted implementation supports the whole
standard including all the library facilities; a conforming
freestanding implementation is only required to provide certain
library facilities: those in <float.h>, <limits.h>, <stdarg.h>, and
<stddef.h>; since AMD1, also those in <iso646.h>; since C99, also
those in <stdbool.h> and <stdint.h>; and since C11, also those in
<stdalign.h> and . In addition, complex types, added in
C99, are not required for freestanding implementations. The standard
also defines two environments for programs, a freestanding
environment, required of all implementations and which may not have
library facilities beyond those required of freestanding
implementations, where the handling of program startup and termination
are implementation-defined, and a hosted environment, which is not
required, in which all the library facilities are provided and startup
is through a function int main (void) or int main (int, char *[]). An
OS kernel would be a freestanding environment; a program using the
facilities of an operating system would normally be in a hosted
implementation.
I am not sure I understand it right...
I will rephrase how I understood it:
Exists two implementations of ISO C standard: a full (named as conforming hosted implementation), and a light (named as conforming freestanding implementation).
Exists two environments (for each of standard's implementation): a hosted environment (for full standard), and a freestanding environment (for light standard).
The light versions is for OS developing. The full versions is for programs, which will work in OS.
And I not understood the phrase about the main function.
I ask to explain me this fragment of text.
It's a bit of both.
The standard defines two runtime environments. One has all of the language, plus a tiny subset of the standard runtime library, plus additional implementation-defined stuff. That's a freestanding environment, and is (as you guessed) intended for programming on the bare metal, e.g. an OS kernel.
The other, more sophisticated environment includes all of the facilities of the above plus all of the standard runtime library. That's a hosted environment, which is intended for application programming.
Now, an implementation is only required to include the facilities of the freestanding environment. If that's all it has, it's called a freestanding implementation. Cross-compilers for deeply embedded microcontrollers are often freestanding implementations, because much of the standard C runtime doesn't make sense or is too big to fit.
Implementing the hosted environment is optional; if an implementation provides the hosted environment it's called a hosted implementation. A hosted implementation must also provide the freestanding environment, i.e. a compilation mode in which only the facilities of a freestanding implementation are available. (This mode would typically be used for compiling things like the C runtime itself, most of which is just more C.)
Finally, the standard signatures for main (int main(void) and int main(int, char **)) are part of the hosted environment. A freestanding environment can use those signatures as well, but it can also define the signature of main to be whatever it likes (void main(void) is common) or use a different name for the entry point.
C11 4/6:
The two forms of conforming implementation are hosted and freestanding. A conforming hosted implementation shall accept any strictly conforming program. A conforming freestanding implementation shall accept any strictly conforming program in which the use of the features specified in the library clause (clause 7) is confined to the contents of the standard headers <float.h>, <iso646.h>, <limits.h>, <stdalign.h>, <stdarg.h>, <stdbool.h>, <stddef.h>, <stdint.h>, and <stdnoreturn.h>.
First note that "implementation", in the context of the C standard, means "the implementation of a C compiler" and nothing else.
As you correctly state in your question, the freestanding implementation is a compiler for a system that isn't intended to have an operative system beneath it. In other words a freestanding implementation compiler produces programs that are either embedded applications running on a "bare bone" CPU, or programs that are operative systems in themselves. While a hosted implementation is a compiler intended for applications running on top of a OS.
The compiler for freestanding applications only needs to provide the above mentioned headers. The rest of the headers (such as stdio.h) are defined in the mentioned "clause 7" of the standard, but they are not mandatory for a freestanding implementation.
Note however that several libraries are not mandatory to neither hosted nor freestanding implementations, for example the complex number library:
C11 7.3.1:
"Implementations that define the macro _ _STDC_NO_COMPLEX_ _ need not
provide this header nor support any of its facilities."
Furthermore, the two different execution environments, freestanding and hosted, allow different syntax for main(), more info can be found here. A very common misunderstanding among programmers is that the only allowed form in C is int main(), which is only true in a hosted environment.
For example, a freestanding program could start at an out-of-reset interrupt service routine. From there it can call a void main() function, or it could call some other function entirely: it is implementation-defined.
What it means is that a freestanding environment is not required to execute your main() function upon startup. For example, it might be looking for _main() instead (the exact name and signature is implementation defined).
Related
When working with strdup on Windows I found out that _strdup is Windows specific, but when I ran the same code on Linux it required strdup without the underscore. Does anyone know the history behind this difference, as-well as some information on how you have dealt with this problem when writing cross-platform code?
There are several functions that are part of the POSIX specification, i.e. Linux and most other UNIX variants, that are not part of standard C. These include strdup, write, read, and others.
The reasoning for the leading underscore is as follows, taken from the MSDN docs:
The Universal C Run-Time Library (UCRT) supports most of the C
standard library required for C++ conformance. It implements the C99
(ISO/IEC 9899:1999) library, with certain exceptions: The type-generic
macros defined in , and strict type compatibility in
. The UCRT also implements a large subset of the POSIX.1
(ISO/IEC 9945-1:1996, the POSIX System Application Program Interface)
C library. However, it's not fully conformant to any specific POSIX
standard. The UCRT also implements several Microsoft-specific
functions and macros that aren't part of a standard.
Functions specific to the Microsoft implementation of Visual C++ are
found in the vcruntime library. Many of these functions are for
internal use and can't be called by user code. Some are documented for
use in debugging and implementation compatibility.
The C++ standard reserves names that begin with an underscore in the
global namespace to the implementation. Both the POSIX functions and
Microsoft-specific runtime library functions are in the global
namespace, but aren't part of the standard C runtime library. That's
why the preferred Microsoft implementations of these functions have a
leading underscore. For portability, the UCRT also supports the
default names, but the Microsoft C++ compiler issues a deprecation
warning when code that uses them is compiled. Only the default names
are deprecated, not the functions themselves. To suppress the warning,
define _CRT_NONSTDC_NO_WARNINGS before including any headers in code
that uses the original POSIX names.
I've handled that by having a #define that check if the program is being compiled for Windows, and if so create another #define to map the POSIX name to the Windows specific name. There are a few choices you can check, although probably the most reliable is _MSC_VER which is defined if MSVC is the compiler.
#ifdef _MSC_VER
#define strdup(p) _strdup(p)
#endif
There is fprintf function in Stdio library.
But how to use it?
The first argument is FILE type.
But I have EFI_FILE_PROTOCOL* File which I got from EFIOpenFile function. How to map to FILE type?
There are hosted environments and freestanding environments.
From the C standard:
The two forms of conforming implementation are hosted and freestanding. A conforming hosted implementation shall accept any strictly conforming program. A conforming freestanding implementation shall accept any strictly conforming program in which the use of the features specified in the library clause (clause 7) is confined to the contents of the standard headers <float.h>, <iso646.h>, <limits.h>, <stdalign.h>, <stdarg.h>, <stdbool.h>, <stddef.h>, <stdint.h>, and <stdnoreturn.h>. A conforming implementation may have extensions (including additional library functions), provided they do not alter the behavior of any strictly conforming program.
So in a freestanding environment (like the UEFI environment you are describing) the C standard doesn't require the fprintf() function to be defined/declared and doesn't require the FILE type to be defined either. Therefore you need to code them on your own.
The question I have is mostly related to section four, paragraph six.
The two forms of conforming implementation are hosted and freestanding. A conforming hosted implementation shall accept any strictly conforming program.
As I understand, this constitutes the typical application environment, with filesystems, allocated memory and threads...
A conforming freestanding implementation shall accept any strictly conforming program in which the use of the features specified in the library clause (clause 7) is confined to the contents of the standard headers <float.h>, <iso646.h>, <limits.h>, <stdalign.h>, <stdarg.h>, <stdbool.h>, <stddef.h>, <stdint.h>, and <stdnoreturn.h>.
... and this constitutes the typical kernel and/or embedded, bare minimum environment that doesn't have standard filesystems, allocated memory or threads (among other things).
A conforming implementation may have extensions (including additional library functions), provided they do not alter the behavior of any strictly conforming program.
It seems as though this gives a hosted implementation the freedom to call itself a hosted or freestanding implementation, and when it comes to filesystems, allocated memory or threads (among other things), these can fall under the extension category so that it can merely implement an interface that returns a value indicating errors every time. Just to name a few:
fopen, fgets and malloc can return NULL
fprintf, fscanf, fputc and fgetc can return EOF
thrd_create can return thrd_error (indicating that "the request could not be honored")
This implies that the distinction section four, paragraph six gives is virtually meaningless. Are there any requirements guaranteeing some actual level of functionality for these functions in hosted and freestanding implementations? For example, is it required that those functions above actually be able to return something other than their corresponding failure values?
The cited paragraph already states it quite well.
A hosted execution environment is also a freestanding, but not vice versa. A compiler need only provide a freestanding implementation. gcc, for example, is strictly speaking freestanding only, as the standard library is not included. However, it assumes it is available when compiling for a hosted environment (the default), assuming the lib is available on the system (like glibc). See here
Simply put, freestanding is just the language. It is not required to support any libraries and just a few headers (mostly for common types and implementation specific stuff like numerical limits, etc.). This implies the standard library need not exist - nor do the corresponding headers. Reason is a freestanding environment most likely will not have such facilities like files, display, etc. It is used for kernels, bare-metal embedded, etc.
Note that gcc for instance will, if compiling for a hosted environment (-fhosted), assume functions used in the standard library have the corresponding meaning and might apply very aggressive optimizations (it has many of those functions built-in). For freestanding, it actually does not, so you can use a function strcmp for instance with completely different semantics. However, it assumes the mem...-functions to exist, as these are used for normal code, e.g. struct assignment.
So, when compiling for bare-metal without a standard library (or a non-standard standard library), you must use -ffreestanding.
If a hosted implementation calls itself freestanding, it is obviously not a hosted implementation anymore. Once it calls itself hosted, however, it has to provide all facilities required by the standard and is not allowed to just implement dummies, but has to provide the semantics as defined in the standard.
Just to state that clear: The cited section allows a freestanding environment to omit all functions of the library, except for the few listed headers. So you are free to supply any other library and use the same names, but do anything you like. As that would be not the standard library, there is no need for compliance.
5.1.2.1 further states that "Any library facilities available to a freestanding program, other than the minimal set required by clause 4, are implementation-defined.". That does support my statement. Sidenote: It also does not require main() as program entry point.
The hosted respectively freestanding implementations which the standard defines are minimal definitions. Both variants are the smallest common denominator of what can reasonably be implemented on a wide range of actual systems.
The rationale for defining such minimal, doable sets is to specify how a program targeting either one of the two flavors must look in order to compile and run with the expected result on ideally all implementations conforming to the respective flavor.
A program strictly conforming to the (i.e., to either) standard is maximally portable.
It goes without saying that actually existing implementations, both freestanding and hosted, typically provide a plethora of extensions, which is fine as far as the standard is concerned — with the one caveat that the extensions must not invalidate a strictly conforming program.
Back to your question: The distinction which the standard makes — the theory — is clear. Actually existing implementations — the practice — fall in a wide spectrum between and beyond the standard's minimal requirements but are bound to the "must not change the behavior" clause regarding strictly conforming programs (targeting hosted or freestanding implementations and not relying on any extensions).
By the way, your examples regarding standard library dummy functions is correct: For freestanding implementations these are just a funny case of allowed extensions: No strictly conforming program targeting freestanding environments would call them anyway. As part of a hosted environment they would be conforming but useless. (One can actually run into situations like that when certain system resources are exhausted, or they could be test stub implementations.)
There are many kinds of C implementations, targeting many kinds of different execution platforms, many of which can provide a variety of useful features and guarantees that others cannot. The authors of the Standard decided that in most cases it should be sufficiently obvious what kinds of features and guarantees should be provided by implementations targeting various platforms and application fields, and how they should be provided, that there would be no need to have a standard concern itself with such details. On the other hand, the number of applications that would require things like file I/O and the number of platforms that could provide them were sufficient to justify recognizing as "special" those implementations which included such features.
In general, implementations which are intended designed for freestanding use will be usable on platforms that would be unable to usefully handle a hosted implementation. While the Standard imposes some requirements beyond what would be practical on some of the smaller C platforms, some almost-conforming implementations of C can be quite usefully employed on processors with only enough storage to hold 256 instructions and 16 bytes' worth of variables. If something like a digital kitchen thermometer/timer gadget doesn't have a file system or console, why should it waste storage on things like descriptors for stdout?
In addition, because the Standard defines no standard means by which freestanding applications can perform I/O, and because different platforms handle I/O differently, almost freestanding applications will be targeted for a particular target platform or range of platforms. A hosted implementation which doesn't expose the natural features or guarantees the underlying platform would provide could be useful for running programs that don't require such features or guarantees. It's not possible for an embedded program to do much of anything without using platform-specific features and guarantees, however, and thus a freestanding implementation which didn't allow a programmer access to such things would be unable to do much. Quality implementations should allow programmers to use any features or guarantees that may help them accomplish what they need to do, though some may require use of compilation options to ensure that they don't do anything wacky. For some reason, it has become fashionable to regard a decision by the Standards Committee that there might be some implementations and application fields where the value of a feature or guarantee wouldn't justify the cost, as an indication that programmers should not expect implementations to provide a feature or guarantee which would be useful in low-level programming and which the platform would provide as essentially zero cost.
There are some free standing environments that cannot become hosted environment. Two known conditions that prevent a free standing environment from becoming hosted environment are:
sizeof(char) == sizeof(int);
sizeof(size_t) < sizeof(int signed);
// SIZE_MAX < INT_MAX
Hosted environment explicitly requires
sizeof(char) < sizeof(int);
// (int)EOF != (char)EOF;
sizeof(int unsigned) <= sizeof(size_t);
// UINT_MAX <= SIZE_MAX
If sizeof(char) == sizeof(int), EOF is undefined.
If argc > SIZE_MAX, you cannot call main.
I am currently learning C. I understand that many common functions, like printf and scanf are not actually part of the C language -- they are part of the "standard library" of functions.
My question is, why aren't such functions built into the language? Is it a philosophical/design consideration? A matter of efficiency when compiling programs? A necessity in order to act as a "middle layer" to ensure compatibility with different operating systems? Something else entirely?
They are part of C. A C implementation consists of a compiler and a library (and other components, like a linker).
The C core language includes facilities that make it possible to write library code that can be used by other programs. The standard library portion of the standard specifies a library that can be implemented using the facilities defined in the core language.
Some languages do have things like a print command built into the language. C's facilities for writing and invoking library code written in C are powerful enough that that's not necessary.
Furthermore, most of the library is optional for "freestanding" implementations (mostly for embedded systems). There are implementations that support the full core language but that don't provide most of the C standard library.
And a compiler and library can be provided separately. For example, gcc is a compiler; it's commonly used with different library implementations on different systems (GNU libc on Linux, "newlib" on Cygwin, the Microsoft library on Windows with MinGW, and so forth). Mixing and matching like that would be much more difficult if the library were integrated into the core language.
The C language standard (the link is to the newest freely available draft) defines C. Section 6 defines the core language; section 7 defines the standard library.
The thing is that standard allows two kinds of conforming implementation: hosted and freestading, see N1570 4/p6:
The two forms of conforming implementation are hosted and
freestanding. A conforming hosted implementation shall accept any
strictly conforming program. A conforming freestanding implementation
shall accept any strictly conforming program that does not use complex
types and in which the use of the features specified in the library
clause (clause 7) is confined to the contents of the standard headers
<float.h>, <iso646.h>, <limits.h>, <stdalign.h>, <stdarg.h>, <stdbool.h>,
<stddef.h>, <stdint.h>, and <stdnoreturn.h>. A conforming implementation may have
extensions (including additional library functions), provided they do
not alter the behavior of any strictly conforming program.
By such design, where the libraries are organized as standard headers it's convienent to simply "cut-off" some header if it is not supported.
Note that C standard defines all headers along with function for standard C library. It's included in C standard indeed, not separate thing somewhere else.
They're part of the language, they're just not part of the grammar.
Factoring I/O out into a separate function library buys you the following:
The grammar becomes easier to parse;
You can target a wider range of platforms; any I/O foibles are handled by the library functions, not by hacking the code generator;
You can implement only as much as is needed to support the platform (i.e., an embedded controller probably doesn't need to read or write formatted output);
I'm surprised that Eclipse can fail to run the simplest program in not only one way but in many way at the same time. The program is
#include <stdio.h>
int main ()
{
int n;
while (scanf("%d", &n) > 0)
{
printf("%d\n", n);
}
return 0;
}
Failure 1: When run in the simulator the output is displayed twice for no reason. The output should be displayed once.
Failure 2: When run with the DE2 board then output is not displayed at all.
Why can't my environment perform like it should?
Since you don't give many details I'm just guessing:
there could be some kind of echoing enabled
on embedded systems <stdio.h> is not required to be supported. <stdio.h> is guaranteed to be available only in hosted environments (i.e. under control of an OS), not in freestanding environments (bare metal).
Quoting from the C99 draft standard N1256:
4. Conformance
[...]
6
The two forms of conforming implementation are hosted and freestanding. A conforming
hosted implementation shall accept any strictly conforming program. A conforming
freestanding implementation shall accept any strictly conforming program that does not
use complex types and in which the use of the features specified in the library clause
(clause 7) is confined to the contents of the standard headers <float.h>,
<iso646.h>, <limits.h>, <stdarg.h>, <stdbool.h>, <stddef.h>, and
<stdint.h>. A conforming implementation may have extensions (including additional
library functions), provided they do not alter the behavior of any strictly conforming
program.
You should check the documentation of the compiler for your board to see which headers it supports.