C preprocessor: Difference between revisions

Content deleted Content added
No edit summary
 
(15 intermediate revisions by 5 users not shown)
Line 14:
}}</ref>
 
The [[C Sharp (programming language)|C#]] programming language also allows for directives, even though they are not read by a preprocessor and they cannot be used for creating macros, and isare generally more intended for features such as conditional compilation.<ref>{{cite web|url=https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/preprocessor-directives|title=C# preprocessor directives|date=14 January 2022 |publisher=Microsoft}}</ref> C# seldom requires the use of the directives, for example code inclusion does not require a preprocessor at all (as C# relies on a package/namespace system like Java, no code needs to be "included").
 
The [[Haskell]] programming language also allows the usage of the C preprocessor, which is invoked by writing <syntaxhighlight lang="Haskell" inline>{-# LANGUAGE CPP #-}</syntaxhighlight> at the top of the file. The accepted preprocessor directives align with those in standard C/C++.
 
Features of the preprocessor are encoded in [[source code]] as [[Directive (programming)|directives]] that start with <code>#</code>.
Line 52:
Until [[C++26]], the C++ keywords <code>import</code>, <code>export</code>, and <code>module</code> were partially handled by the preprocessor as well.
 
The Haskell programming language also accepts C preprocessor directives, which is invoked by writing <syntaxhighlight lang="Haskell" inline>{-# LANGUAGE CPP #-}</syntaxhighlight> at the top of the file. The accepted preprocessor directives align with those in standard C/C++.
Haskell also accepts C preprocessor directives.
 
=== C# ===
Line 133:
 
==== 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 thoughif it's is 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><ref>{{Cite web|title=#embed - a scannable, tooling-friendly binary resource inclusion mechanism|url=https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2025/p1967r14.html|website=open-std.org }}</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]].
 
Line 139:
 
<syntaxhighlight lang="cpp">
const unsigned char icon_display_dataiconDisplayData[] = {
#embed "art.png"
};
 
/* specify any type which can be initialized form integer constant expressions will do */
const char reset_blobresetBlob[] = {
#embed "data.bin"
};
 
/* attributes work just as well */
const signed char aligned_data_stralignedDataString[] __attribute__ ((aligned (8))) = {
#embed "attributes.xml"
};
Line 256:
One little-known usage pattern of the C preprocessor is known as [[X Macro|X-Macros]].<ref name="X_macros">[http://liw.iki.fi/liw/texts/cpp-trick.html Wirzenius, Lars. C "Preprocessor Trick For Implementing Similar Data Types". Retrieved January 9, 2011]</ref><ref>{{cite journal | last = Meyers | first = Randy |date=May 2001 | title = The New C: X Macros | journal = Dr. Dobb's Journal | url = http://www.ddj.com/cpp/184401387 | access-date = 1 May 2008 }}</ref><ref>{{cite journal | last = Beal | first = Stephan |date=August 2004 | title = Supermacros | url = http://wanderinghorse.net/computing/papers/#supermacros | access-date = 27 October 2008 }}</ref> An X-Macro is a [[header file]]. Commonly, these use the extension <code>.def</code> instead of the traditional <code>.h</code> . This file contains a list of similar macro calls, which can be referred to as "component macros." The include file is then referenced repeatedly.
 
Many compilers define additional, non-standard macros. A common reference for these macros is the [httphttps://predef.sourceforge.net/ Pre-defined C/C++ Compiler Macros project], which lists "various pre-defined compiler macros that can be used to identify standards, compilers, operating systems, hardware architectures, and even basic run-time libraries at compile-time."
 
Most compilers targeting [[Microsoft Windows]] implicitly define <code>_WIN32</code>.<ref>[http://msdn.microsoft.com/en-us/library/b0084kay.aspx List of predefined ANSI C and Microsoft C++ implementation macros.]</ref> This allows code, including preprocessor commands, to compile only when targeting Windows systems. A few compilers define <code>WIN32</code> instead. For such compilers that do not implicitly define the <code>_WIN32</code> macro, it can be specified on the compiler's command line, using <code>-D_WIN32</code>.
Line 346:
==Non-standard features ==
 
=== Pragma<code>#pragma</code> ===
The <code>#pragma</code> directive is defined by standard languages, but with little or no requirements for syntax after its name so that compilers are free to define subsequent syntax and associated behavior. For instance, a pragma is often used to allow suppression of error messages, manage heap and stack debugging and so on.
 
Line 359:
Some [[Unix]] preprocessors provided an [[assertion (computing)|assertion]] feature {{endash}} which has little similarity to standard library assertions.<ref>[https://gcc.gnu.org/onlinedocs/cpp/Obsolete-Features.html GCC Obsolete features]</ref>
 
=== Include next<code>#include_next</code> ===
GCC provides <code>#include_next</code> for chaining headers of the same name.<ref>{{Cite web|url=https://gcc.gnu.org/onlinedocs/cpp/Wrapper-Headers.html|title = Wrapper Headers (The C Preprocessor)}}</ref>
 
=== Import<code>#import</code> ===
Unlike C and C++, Objective-C includes an <code>#import</code> directive that is like <code>#include</code> but results in a file being included only once {{endash}} eliminating the need for include guards and [[pragma once|<code>#pragma once</code>]].
 
Line 370:
</syntaxhighlight>
 
In [[Microsoft Visual C++]] (MSVC), there also exists an <code>#import</code> preprocessor directive, used to import type libraries.<ref>{{Cite web|title=#import directive (C++)|url=https://learn.microsoft.com/en-us/cpp/preprocessor/hash-import-directive-cpp|title publisher= #import directive (C++)learn.microsoft.com}}</ref> It is a nonstandard directive.
 
<syntaxhighlight lang="cpp">
Line 378:
The Objective-C directive should not be confused with the C++ keyword <code>import</code>, which is used to import C++ [[Modules (C++)|modules]] (since [[C++20]]), and is not a preprocessor directive.
 
=== NullableNull directive ===
The null directive, which consists only of the <code>#</code> character, alone on a single line, is a non-standard directive in Microsoft Visual C++. It has no effect.<ref>{{Cite web|title=Null directive|url=https://learn.microsoft.com/en-us/cpp/preprocessor/null-directive|publisher=learn.microsoft.com}}</ref>
 
=== <code>#nullable</code> ===
The <code>#nullable</code> directive in C# is used to enable and disable nullable reference types. To enable them, use <code>#nullable enable</code>, and <code>#nullable disable</code> to disable them.
 
Line 394 ⟶ 397:
This directive does not exist in C/C++.
 
=== Region<code>#region</code> ===
The <code>#region</code> and <code>#endregion</code> directives in C# are used to expand/collapse sections of code in IDEs, and has no effect on actual compilation of the program. It is primarily used for code organisation and readability.
<syntaxhighlight lang="csharp">
Line 412 ⟶ 415:
#pragma region Helper methods
 
void log(const std::string&string_view message) {
std::println(message);
}
 
#pragma endregion
</syntaxhighlight>
 
=== <code>#using</code> ===
[[C++/CLI]] has the <code>#using</code> directive, which is used to import metadata into a program from a Microsoft Intermediate Language file (such as a {{mono|.dll}} file).<ref>{{Cite web|title=#using directive (C++/CLI)|url=https://learn.microsoft.com/en-us/cpp/preprocessor/hash-using-directive-cpp|publisher=learn.microsoft.com|date=29 June 2022}}</ref>
 
<syntaxhighlight lang="c++">
#using <MyComponent.dll>
#using "AssemblyA.dll"
#using "AssemblyB.dll"
 
using namespace System;
 
public ref class B {
public void Test(A a) {
// ...
}
};
 
int main(array<String^>^ args) {
A a;
B b;
B.Test(a);
}
</syntaxhighlight>
 
Line 442 ⟶ 468:
|title=An empirical analysis of c preprocessor use |journal=IEEE Transactions on Software Engineering |url = http://dl.acm.org/citation.cfm?id=631305
|date = December 2002
|volume=28 |issue=12 |pages=1146–1170 |doi=10.1109/TSE.2002.1158288 |bibcode=2002ITSEn..28.1146E |url-access=subscription }}</ref>
 
;Hidden multiple evaluation
Line 507 ⟶ 533:
* [https://gcc.gnu.org/onlinedocs/cpp/index.html GNU CPP online manual]
* [http://msdn.microsoft.com/en-us/library/y4skk93w(VS.80).aspx Visual Studio .NET preprocessor reference]
* [httphttps://predef.sourceforge.net/ Pre-defined C/C++ Compiler Macros project]: lists "various pre-defined compiler macros that can be used to identify standards, compilers, operating systems, hardware architectures, and even basic run-time libraries at compile-time"
 
{{CProLang}}