C preprocessor: Difference between revisions

Content deleted Content added
No edit summary
Line 107:
 
=== File inclusion ===
There are two directives in the C preprocessor for including contents of files:
To include the content of one file into another, the preprocessor replaces a line that starts with <code>#include</code> with the content of the file specified after the directive. The inclusion may be logical in the sense that the resulting content may not be stored on disk and certainly is not overwritten to the source file.
* <code>#include</code>, used for directly including the contents of a file in-place (typically containing code of some kind)
* <code>#embed</code>, used for directly including or embedding the contents of a binary resource in-place
 
==== Binary resourceCode inclusion ====
To include the content of one file into another, the preprocessor replaces a line that starts with <code>#include</code> with the content of the file specified after the directive. The inclusion may be logical in the sense that the resulting content may not be stored on disk and certainly is not overwritten to the source file. The file being included need not contain any sort of code, as this directive will copy the contents of whatever file is included in-place, but the most typical use of <code>#include</code> is to include a header file (or in some rarer cases, a source file).
 
In the following example code, the preprocessor replaces the line <code>#include &lt;stdio.h&gt;</code> with the content of the standard library header file named 'stdio.h' in which the [[Function (computer programming)|function]] <code>printf()</code> and other symbols are declared.
Line 125 ⟶ 130:
 
To prevent including the same file multiple times which often leads to a compiler error, a header file typically contains an [[include guard]] or if supported by the preprocessor [[pragma once|<code>#pragma once</code>]] to prevent multiple inclusion.
 
==== Binary resource inclusion ====
[[C23 (C standard revision)|C23]] and [[C++26]] introduce the <code>#embed</code> directive for '''binary resource inclusion''' which allows including the content of a binary file into a source even though it's not valid C code.<ref>{{cite web |title=WG14-N3017 : #embed – a scannable, tooling-friendly binary resource inclusion mechanism |url=https://www.open-std.org/jtc1/sc22/wg14/www/docs/n3017.htm |website=open-std.org |archive-url=https://web.archive.org/web/20221224045304/https://www.open-std.org/jtc1/sc22/wg14/www/docs/n3017.htm |archive-date=24 December 2022 |date=2022-06-27 |url-status=live}}</ref>
This allows binary resources (like images) to be included into a program without requiring processing by external tools like <code>xxd -i</code> and without the use of [[string literal]]s which have a length limit on [[MSVC]]. Similarly to <code>xxd -i</code> the directive is replaced by a comma separated list of integers corresponding to the data of the specified resource. More precisely, if an array of type {{code|unsigned char}} is initialized using an <code>#embed</code> directive, the result is the same as-if the resource was written to the array using <code>[[fread]]</code> (unless a parameter changes the embed element width to something other than <code>[[Limits.h|CHAR_BIT]]</code>). Apart from the convenience, <code>#embed</code> is also easier <!--than what?--> for compilers to handle, since they are allowed to skip expanding the directive to its full form due to the [[as-if rule]].
 
The file to embed is specified the same as for <code>#include</code> {{endash}} either with [[angle brackets|brackets]] or double quotes. The directive also allows certain parameters to be passed to it to customize its behavior. The C standard defines some parameters and implementations may define additional. The <code>limit</code> parameter is used to limit the width of the included data. It is mostly intended to be used with "infinite" files like [[urandom]]. The <code>prefix</code> and <code>suffix</code> parameters allow for specifying a prefix and suffix to the embedded data. Finally, the <code>if_empty</code> parameter replaces the entire directive if the resource is empty. All standard parameters can be surrounded by double underscores, just like standard attributes on C23, for example <code>__prefix__</code> is interchangeable with <code>prefix</code> <!-- This will not be the case in C++ once the feature is ported over. See: P1967-->. Implementation-defined parameters use a form similar to [[C++11#Attributes|attribute]] syntax (e.g., <code>vendor::attr</code>) but without the square brackets. While all standard parameters require an argument to be passed to them (e.g., limit requires a width), this is generally optional and even the set of parentheses can be omitted if an argument is not required, which might be the case for some implementation-defined parameters.
 
<syntaxhighlight lang="cpp">
const unsigned char icon_display_data[] = {
#embed "art.png"
};
 
/* specify any type which can be initialized form integer constant expressions will do */
const char reset_blob[] = {
#embed "data.bin"
};
 
/* attributes work just as well */
const signed char aligned_data_str[] __attribute__ ((aligned (8))) = {
#embed "attributes.xml"
};
 
int main() {
return
#embed </dev/urandom> limit(1)
;
</syntaxhighlight>
 
=== Conditional compilation ===
Line 280 ⟶ 313:
A macro argument cannot be combined with additional text and then stringified. However, a series of adjacent string literals and stringified arguments, also string literals, are concatenated by the C compiler.
 
====Token concatenation====
The '''token pasting operator''', denoted by <code>##</code>, concatenates two tokens into one. For definition:
 
Line 308 ⟶ 341:
// Microsoft
#pragma message("Do not use ABC, which is deprecated. Use XYZ instead.")
</syntaxhighlight>
 
=== Binary resource inclusion ===
[[C23 (C standard revision)|C23]] and [[C++26]] introduce the <code>#embed</code> directive for '''binary resource inclusion''' which allows including the content of a binary file into a source even though it's not valid C code.<ref>{{cite web |title=WG14-N3017 : #embed – a scannable, tooling-friendly binary resource inclusion mechanism |url=https://www.open-std.org/jtc1/sc22/wg14/www/docs/n3017.htm |website=open-std.org |archive-url=https://web.archive.org/web/20221224045304/https://www.open-std.org/jtc1/sc22/wg14/www/docs/n3017.htm |archive-date=24 December 2022 |date=2022-06-27 |url-status=live}}</ref>
This allows binary resources (like images) to be included into a program without requiring processing by external tools like <code>xxd -i</code> and without the use of [[string literal]]s which have a length limit on [[MSVC]]. Similarly to <code>xxd -i</code> the directive is replaced by a comma separated list of integers corresponding to the data of the specified resource. More precisely, if an array of type {{code|unsigned char}} is initialized using an <code>#embed</code> directive, the result is the same as-if the resource was written to the array using <code>[[fread]]</code> (unless a parameter changes the embed element width to something other than <code>[[Limits.h|CHAR_BIT]]</code>). Apart from the convenience, <code>#embed</code> is also easier <!--than what?--> for compilers to handle, since they are allowed to skip expanding the directive to its full form due to the [[as-if rule]].
 
The file to embed is specified the same as for <code>#include</code> {{endash}} either with [[angle brackets|brackets]] or double quotes. The directive also allows certain parameters to be passed to it to customize its behavior. The C standard defines some parameters and implementations may define additional. The <code>limit</code> parameter is used to limit the width of the included data. It is mostly intended to be used with "infinite" files like [[urandom]]. The <code>prefix</code> and <code>suffix</code> parameters allow for specifying a prefix and suffix to the embedded data. Finally, the <code>if_empty</code> parameter replaces the entire directive if the resource is empty. All standard parameters can be surrounded by double underscores, just like standard attributes on C23, for example <code>__prefix__</code> is interchangeable with <code>prefix</code> <!-- This will not be the case in C++ once the feature is ported over. See: P1967-->. Implementation-defined parameters use a form similar to [[C++11#Attributes|attribute]] syntax (e.g., <code>vendor::attr</code>) but without the square brackets. While all standard parameters require an argument to be passed to them (e.g., limit requires a width), this is generally optional and even the set of parentheses can be omitted if an argument is not required, which might be the case for some implementation-defined parameters.
 
<syntaxhighlight lang="cpp">
const unsigned char icon_display_data[] = {
#embed "art.png"
};
 
/* specify any type which can be initialized form integer constant expressions will do */
const char reset_blob[] = {
#embed "data.bin"
};
 
/* attributes work just as well */
const signed char aligned_data_str[] __attribute__ ((aligned (8))) = {
#embed "attributes.xml"
};
 
int main() {
return
#embed </dev/urandom> limit(1)
;
</syntaxhighlight>