C++ syntax: Difference between revisions

Content deleted Content added
Undid revision 1287318228 by 129.97.124.1 (talk) actually a bad idea, nvm
Tags: Mobile edit Mobile web edit
 
(36 intermediate revisions by 12 users not shown)
Line 3:
[[File:Orwell Dev-Cpp zh cn.jpg|thumb|300px|A snippet of C++ code]]
 
The '''syntax of C++''' is [[syntax|the set of rules]] defining how a [[C++]] program is written and compiled.
 
C++ syntax is largely inherited from the syntax of its ancestor language [[C (programming language)|C]], and has influenced the syntax of several later languages including but not limited to [[Java (programming language)|Java]], [[C Sharp (programming language)|C#]], and [[Rust (programming language)|Rust]].
Line 38:
* <code>alignas</code>
* <code>alignof</code>
* <code>and</code>
* <code>and_eq</code>
* <code>asm</code>
* <code>auto</code>
* <code>bitand</code>
* <code>bitor</code>
* <code>bool</code>
* <code>break</code>
Line 53 ⟶ 49:
* <code>char32_t</code>
* <code>class</code>
* <code>compl</code>
* <code>concept</code>
* <code>const</code>
Line 90 ⟶ 85:
* <code>new</code>
* <code>noexcept</code>
* <code>not</code>
* <code>not_eq</code>
* <code>nullptr</code>
* <code>operator</code>
* <code>or</code>
* <code>or_eq</code>
* <code>private</code>
* <code>protected</code>
Line 128 ⟶ 119:
* <code>wchar_t</code>
* <code>while</code>
{{div col end}}
 
The keyword [[restrict|<code>restrict</code>]], though present in C, is not standard in C++, though some compilers may support it. The keyword <code>fortran</code>, a conditionally supported keyword in C which denotes linkage for the [[Fortran]] programming language, is conditionally supported in C++.
 
=== Alternative operator keywords ===
The following words are reserved keywords, but are used as alternative spellings for operators and tokens that use non-ISO646 characters.
{{div col|colwidth=15em}}
* <code>and</code>
* <code>and_eq</code>
* <code>bitand</code>
* <code>bitor</code>
* <code>compl</code>
* <code>not</code>
* <code>not_eq</code>
* <code>or</code>
* <code>or_eq</code>
* <code>xor</code>
* <code>xor_eq</code>
Line 167 ⟶ 174:
* <code>#__has_embed</code>
{{div col end}}
 
The following macros are often ubiquitously used in C and thus C++ as well:
* <code>NULL</code> (expands to <code>(void*)0</code>, used prior to the introduction of <code>nullptr</code> to represent a null pointer)
* <code>NDEBUG</code> (a macro meaning "no-debug", used primarily to control whether <code>assert()</code> calls are ignored)
* <code>assert()</code> (a macro with arguments, which terminates the program if the argument evaluates to <code>false</code>, <code>0</code>, or <code>nullptr</code>, and can be disabled by <code>NDEBUG</code>)
 
=== Code blocks ===
Line 190 ⟶ 202:
C++ has two kinds of [[Comment (computer programming)|comments]]: ''traditional comments'' and ''end-of-line comments''.
 
Traditional comments, also known as block comments, start with <code>/*</code> and end with <code>*/</code>, they may span across multiple lines.
 
<syntaxhighlight lang="cpp">
Line 232 ⟶ 244:
 
int main(int argc, char* argv[]) {
std::println("argc = {}", argc);
for (size_t i = 0; i < argc; ++i) {
std::println("argv[{}] = {}", i, argv[i]);
}
}
</syntaxhighlight>
Line 277 ⟶ 290:
 
=== Inline Assembly ===
Programs developed in C or C++ often utilize inline assembly to take advantage of its low-level functionalities, greater speed, and enhanced control compared to high-level programming languages<ref name="Bokil2021">Bokil, Milind A. (2021). "[https://www.researchgate.net/publication/354744729_Writing_Assembly_Routines_within_CC_and_Java_Programs Writing Assembly Routines within C/C++ and Java Programs]". ResearchGate. Retrieved April 1, 2025.</ref><ref name="Vilhena2024">{{cite journal | url=https://doi.org/10.1145/3689749 | doi=10.1145/3689749 | title=Extending the C/C++ Memory Model with Inline Assembly | date=2024 | last1=De Vilhena | first1=Paulo Emílio | last2=Lahav | first2=Ori | last3=Vafeiadis | first3=Viktor | last4=Raad | first4=Azalea | journal=Proceedings of the ACM on Programming Languages | volume=8 | pages=1081–1107 | arxiv=2408.17208 }}</ref> when optimizing for performance is essential. C++ provides support for embedding [[Assembly language|assembly]] language using asm declarations,<ref name="cppreferenceAsm">cppreference.com contributors. "[https://en.cppreference.com/w/cpp/language/asm asm declaration]". ''cppreference.com''. Retrieved April 1, 2025.</ref>, but the compatibility of [[inline assembly]] varies significantly between [[compilers]] and architectures. Unlike high-level language features such as [[Python (programming language)|Python]] or [[Java (programming language) |Java]], assembly code is highly dependent on the underlying processor and compiler implementation.
 
==== Variations across compilers ====
Different C++ compilers implement inline assembly in distinct ways.
 
*GCC ([[GNU Compiler Collection]]) and [[Clang]] :<ref>{{Cite web |title=Extended Asm (Using the GNU Compiler Collection) |url=https://gcc.gnu.org/onlinedocs/gcc/Extended-Asm.html |website=GCC Online Documentation |publisher=GNU Project |access-date=April 1, 2025}}</ref>: Use the GCC extended inline assembly syntax. Using <syntaxhighlight lang="C++" inline>__asm__</syntaxhighlight> keyword instead of <syntaxhighlight lang="C++" inline>asm</syntaxhighlight> when writing code that can be compiled with <syntaxhighlight lang="C++" inline>-ansi</syntaxhighlight> and <syntaxhighlight lang="C++" inline>-std</syntaxhighlight> options, which allows specifying input/output operands and clobbered registers. This approach is widely adopted, including by Intel<ref name="IntelInlineAssembly">Intel Corporation. "[https://www.intel.com/content/www/us/en/docs/cpp-compiler/developer-guide-reference/2021-9/inline-assembly.html Inline Assembly]". ''Intel® C++ Compiler Classic Developer Guide and Reference'', Version 2021.9. Retrieved April 1, 2025.</ref> and IBM<ref name="IBMInlineAssembly">IBM. "[https://www.ibm.com/docs/en/xl-c-aix/13.1.3?topic=statements-inline-assembly-extension Inline assembly statements (IBM extension)]". ''IBM Documentation''. Retrieved April 1, 2025.</ref> compilers.
*MSVC ([[Microsoft Visual C++]]): The inline assembler is built into the compiler. Previously supported inline assembly via the <syntaxhighlight lang="C++" inline>__asm</syntaxhighlight> keyword, but this support has been removed in 64-bit mode, requiring separate .asm modules instead.<ref>{{Cite web |title=Inline Assembler Overview |url=https://learn.microsoft.com/en-us/cpp/assembler/inline/inline-assembler-overview?view=msvc-170 |website=Microsoft Learn |publisher=Microsoft |access-date=1 April 2025}}</ref>
 
*TI ARM Clang and Embedded Compilers:<ref>{{Cite web |title=Interfacing C and C++ With Assembly Language |url=https://software-dl.ti.com/codegen/docs/tiarmclang/compiler_tools_user_guide/compiler_manual/runtime_environment/interfacing-c-and-c-with-assembly-language-stdz0544217.html#interfacing-c-and-c-with-assembly-language |website=Texas Instruments |publisher=Texas Instruments Incorporated |date=February 23, 2025 |access-date=April 1, 2025}}</ref> Some embedded system compilers, like Texas Instruments' TI Arm Clang, allow inline assembly but impose stricter rules to avoid conflicts with register conventions and calling conventions.
*MSVC ([[Microsoft Visual C++]]): The inline assembler is built into the compiler. Previously supported inline assembly via the <syntaxhighlight lang="C++" inline>__asm</syntaxhighlight> keyword, but this support has been removed in 64-bit mode, requiring separate .asm modules instead<ref>{{Cite web |title=Inline Assembler Overview |url=https://learn.microsoft.com/en-us/cpp/assembler/inline/inline-assembler-overview?view=msvc-170 |website=Microsoft Learn |publisher=Microsoft |access-date=1 April 2025}}</ref>.
 
*TI ARM Clang and Embedded Compilers <ref>{{Cite web |title=Interfacing C and C++ With Assembly Language |url=https://software-dl.ti.com/codegen/docs/tiarmclang/compiler_tools_user_guide/compiler_manual/runtime_environment/interfacing-c-and-c-with-assembly-language-stdz0544217.html#interfacing-c-and-c-with-assembly-language |website=Texas Instruments |publisher=Texas Instruments Incorporated |date=February 23, 2025 |access-date=April 1, 2025}}</ref>: Some embedded system compilers, like Texas Instruments' TI Arm Clang, allow inline assembly but impose stricter rules to avoid conflicts with register conventions and calling conventions.
 
==== Interoperability between C++ and Assembly ====
C++ provides two primary methods of integrating ASM code.
 
1. Standalone assembly files – Assembly code is written separately and linked with C++ code. <ref>{{cite web |url=https://wiki.osdev.org/C%2B%2B_to_ASM_linkage_in_GCC |title=C++ to ASM linkage in GCC |website=OSDev Wiki |access-date=1 April 2025}}</ref>
 
2. [[Inline assembly]] – Assembly code is embedded within C++ code using compiler-specific extensions.
Line 500 ⟶ 511:
</syntaxhighlight>
 
It is also possible to raise exceptions purposefully, using the <syntaxhighlight lang="C++" inline>throw</syntaxhighlight> keyword; these exceptions are handled in the usual way. In some cases, exceptions cannot be used due to technical reasons. One such example is a critical component of an embedded system, where every operation must be guaranteed to complete within a specified amount of time. This cannot be determined with exceptions as no tools exist to determine the maximum time required for an exception to be handled.<ref>{{Cite book |title=The C++ Programming Language |last=Stroustrup |first=Bjarne |publisher=Addison Wesley |year=2013 |isbn=9780321563842 |pages=349}}</ref> Unlike languages like Java, C# and D, which only allows objects that extend <code>Throwable</code> (whose subclasses are <code>Error</code> and <code>Exception</code>), C++ allows anything, both primitive types and objects, to be thrown and caught. C++ does not have an Error class like those languages, but has an Exception class (<code>std::exception</code>). In the aforementioned languages, the distinction between Error and Exception is made in that Errors usually represent irrecoverable states, while Exceptions are more acceptable to catch and represent circumstances that are normal to occur throughout the execution of a program.
 
Unlike [[Signal handler|signal handling]], in which the handling function is called from the point of failure, exception handling exits the current scope before the catch block is entered, which may be located in the current function or any of the previous function calls currently on the stack.
Line 509 ⟶ 520:
== Concepts ==
{{main|Concepts (C++)}}
Concepts are an extension to the [[template (C++)|templates]] feature provided by the [[C++]] programming language. Concepts are named [[Boolean value|Boolean]] predicates on template parameters, evaluated at [[compile time]]. A concept may be associated with a template ([[class (C++)|class]] template, [[function (computer programming)|function]] template, [[member function]] of a class template, [[Template _ (C%2B%2B++)#Variable_templatesVariable templates|variable template]], or [[Template_Template (C%2B%2B++)#Template_aliasesTemplate aliases|alias template]]), in which case it serves as a ''constraint'': it limits the set of arguments that are accepted as template parameters.
 
The main uses of concepts are:
Line 528 ⟶ 539:
* <code>C1</code>: A type-constraint. This kind replaces <code>class</code> or [[Typename|<code>typename</code>]] for declaring a [[TypeParameter|type template parameter]]. When using a concept instead of the former two the type is constraint.
* <code>C2</code>: A requires-clause. Whenever a type-constraint does not work, for example, because the concept takes multiple parameters, a requires-clause can be used to apply more elaborated constraints.
* <code>C3 / C4</code>: A constrained placeholder type. The same syntax is available for [[Type_inferenceType inference|placeholder]] variable aka. <code>auto</code> variable. C++20 added [[abbreviated function template]]s which use <code>auto</code> as a placeholder type in the parameter declaration.<ref>{{ cite web | title = ISO/IEC 14882:2020 | publisher = ISO | date = December 2020 | url = http://www.iso.org/iso/iso_catalogue/catalogue_tc/catalogue_detail.htm?csnumber=79358 | access-date =14 July 2022 }}</ref> A constrained placeholder type allows to put constraints on the automatically deduced return type of a function or a variable.
* <code>C5</code>: A trailing requires-clause. This form is similar to <code>C2</code> with one notable exception. A trailing requires-clause can be applied to a function in a class template. This allows the function to remain a regular, template-free function, which can be enabled or disabled depending on the functions trailing requires-clause.
 
Line 536 ⟶ 547:
=== Headers ===
{{see also|Include directive}}
Traditionally (prior to [[C++20]]), code inclusion in C++ followed the ways of C, in which code was imported into another file using the preprocessor directive <code>#include</code>, which would copy the contents of the file into the other file.
 
Traditionally, C++ code would be divided between a header file (typically with extension {{mono|.h}}, {{mono|.hpp}} or {{mono|.hh}}) and a source file (typically with extension {{mono|.cpp}} or {{mono|.cc}}). The header file usually contained declarations of symbols while the source file contained the actual implementation, such as function implementations. This separation was often enforced because <code>#include</code>ing code into another file would result in it being reprocessed for each file it was included by, resulting in increased compilation times if the compiler had to reprocess the same source repeatedly.
 
Headers often also forced the usage of [[include guard|{{mono|#include}} guards]] or [[pragma once|{{mono|#pragma once}}]] to prevent a header from potentially being included into a file multiple times.
 
The C++ standard library remains accessible through headers, however since C++23 it has been made accessible using modules as well.<ref name=cppreferencemodules /><ref name=cppreferencestandardlibrary /> Even with the introduction of modules, headers continue to play a role in modern C++, as existing codebases have not completely migrated to modules.
 
==== Header units ====
Headers are traditionally included via textual inclusion by the preprocessor using <code>#include</code>, while modules are included during compilation through <code>import</code>. However, headers may also be imported using <code>import</code>, even if they are not declared as modules – these are called "header units", and they are designed to allow existing codebases to migrate from headers to modules more gradually.<ref>{{cite web|url=https://learn.microsoft.com/en-us/cpp/build/walkthrough-header-units?view=msvc-170|title=Walkthrough: Build and import header units in Microsoft Visual C++|date=12 April 2022 |publisher=Microsoft}}</ref> The syntax is similar to including a header, with the difference being that <code>#include</code> is replaced with <code>import</code> and a semicolon is placed at the end of the statement. Header units automatically export all symbols, and differ from proper modules in that they allow the emittance of macros, meaning all who import the header unit will obtain its contained macros. This offers minimal breakage between migration to modules. The semantics of searching for the file depending on whether quotation marks or angle brackets are used apply here as well. For instance, one may write <syntaxhighlight lang="C++" inline>import <string>;</syntaxhighlight> to import the <code><string></code> header, or <syntaxhighlight lang="C++" inline>import "MyHeader.h";</syntaxhighlight> to import the file <code>"MyHeader.h"</code> as a header unit. Most build systems, such as [[CMake]], do not support this feature yet.
 
=== Modules ===
{{main|Modules (C++)}}
{{excerpt|Precompiled header|Modules}}
Modules do not use the C preprocessor at all, and are instead handled directly by the compiler.<ref name=cppreferencemodules /> A module is declared using <code>export module</code>, and the beginning of the module preamble begins with <code>module;</code>. Exported symbols which will be made accessible to importing translation units are marked <code>export</code>, and a module is imported into the translation unit using <code>import</code>. Modules do not export macros, due to being handled after the preprocessing step.
 
Modules may also have partitions, which cannot be imported individually but are owned by a larger module.
 
==== Example ====
{{excerpt|Modules (C++)|Example}}
A simple example of using C++ modules is as follows:
 
== Attributes ==
Since C++11, C++ has supported attribute specifier sequences.<ref>{{cite web|title=Attribute specifier sequence (since C++11)|url=https://cppreference.com/w/cpp/language/attributes.html|website=cppreference.com|access-date=6 June 2025}}</ref> Attributes can be applied to any symbol that supports them, including classes, functions/methods, and variables, and any symbol marked with an attribute will be specifically treated by the compiler as necessary. These can be thought of as similar to [[Java annotation]]s for providing additional information to the compiler, however they differ in that attributes in C++ are not metadata that is meant to be accessed using reflection. C++26 adds support for annotations for reflection. Furthermore, one cannot create custom attributes in C++, unlike in Java where one may define custom annotations in addition to the standard ones. However, C++ does have implementation/vendor-specific attributes which are non-standard. These typically have a namespace associated with them. For instance, GCC and Clang have attributes under the <code>gnu::</code> namespace, and all such attributes are of the form {{cpp|[[gnu::*]]}}.
 
One may apply multiple attributes as a list, for instance {{cpp|[[A, B, C]]}} (where <code>A</code>, <code>B</code>, and <code>C</code> are attributes). Furthermore, attributes may also accept arguments, like {{cpp|[[A("This is a parameter")]]}}. The following is an example of using some attributes in C++.
 
{{mono|MyClass.cppm}}
<syntaxhighlight lang="cpp">
class MyObject {
export module myproject.MyClass;
private:
[[no_unique_address]]
int x;
public:
[[nodiscard]]
bool satisfiesProperty() const noexcept {
if ([[likely]] x > 0) {
return true;
}
return false;
}
};
</syntaxhighlight>
 
=== Standard attributes ===
import std;
The C++ standard defines the following attributes:
 
Legend:<br>
using String = std::string;
{{color box|#E6E6B7}}: Deprecated<br>
{{color box|#F99}}: Removed
 
{| class="wikitable"
export namespace myproject {
! Name !! Description
class MyClass {
|-
private:
| {{cpp|[[noreturn]]}}
int x;
|| Indicates that the specified function will not return to its caller.
String name;
|-
public:
| style="background:#F99" | {{cpp|[[carries_dependency]]}}
MyClass(int x, const String& name):
| style="background:#F99" | Indicates that the dependency chain in release-consume <code>std::memory_order</code> propagates in and out of the function. Removed since C++26.
x{x}, name{name} {}
|-
| {{cpp|[[deprecated]]}}<br>{{cpp|[[deprecated("reason")]]}}
|| Indicates that the use of the marked symbol is allowed but discouraged/deprecated for the reason specified (if given).
|-
| {{cpp|[[fallthrough]]}}
|| Indicates that the fall through from the previous case label is intentional.
|-
| {{cpp|[[maybe_unused]]}}
|| Suppresses compiler warnings on an unused entity.
|-
| {{cpp|[[nodiscard]]}}<br>{{cpp|[[nodiscard("reason")]]}}
|| Issues a compiler warning if the return value of the marked symbol is discarded or ignored for the reason specified (if given).
|-
| {{cpp|[[likely]]}}<br>{{cpp|[[unlikely]]}}
|| Indicates that the compiler should optimise for the case where a path of execution through a statement is more or less likely to occur than the other(s).
|-
| {{cpp|[[no_unique_address]]}}
|| Indicates that a non-static data member need not have an address distinct from all other non-static data members of its class.
|-
| {{cpp|[[assume(expression)]]}}
|| Indicates that the given expression always evaluates to {{cpp|true}} at a given point, allowing the compiler to make optimisations based on that information.
|-
| {{cpp|[[indeterminate]]}}
|| Indicates that an object bears an indeterminate value if it is not initialised.
|-
| {{cpp|[[unsequenced]]}}
|| Indicates that a function is stateless, effectless, idempotent and independent.
|-
| {{cpp|[[reproducible]]}}
|| Indicates that a function is effectless and idempotent.
|}
 
=== Scoped attributes ===
int getX() const noexcept {
As mentioned previously, GCC and Clang have scoped (namespaced) attributes, such as {{cpp|[[gnu::always_inline]]}}, {{cpp|[[gnu::hot]]}}, and {{cpp|[[gnu::const]]}}. To apply multiple scoped attributes, one may write:
return x;
<syntaxhighlight lang="cpp">
}
[[gnu::always_inline]] [[gnu::hot]] [[gnu::const]] [[nodiscard]]
inline int f(); // declare f with four attributes
[[gnu::always_inline, gnu::const, gnu::hot, nodiscard]]
int f(); // same as above, but uses a single attr specifier that contains four attributes
// C++17:
[[using gnu : const, always_inline, hot]] [[nodiscard]]
int f[[gnu::always_inline]](); // an attribute may appear in multiple specifiers
</syntaxhighlight>
 
== Reflection ==
void setX(int newX) noexcept {
In addition to basic metaprogramming provided in header <code><type_traits></code>, [[C++26]] introduces compile-time reflection. Compile-time reflection capabilities can be accessed in header <code><meta></code> and declarations are stored in namespace <code>std::meta</code>.
x = newX;
};
 
=== Annotations ===
String getName() const noexcept {
Most declarations can have annotations attached, which are just values associated with that declaration. Like [[Java annotation]]s, annotations can be accessed using reflection. Annotations are different from attributes as attributes are primarily a means to communicate information to the compiler, while annotations are a feature of reflection and allow arbitrary constants and metadata to be attached, making them customisable to programs, unlike attributes. This allows for bridging the communication between the library API and the user.
return name;
<syntaxhighlight lang="cpp">
}
using custom::Debug;
using custom::EnumFlag;
using custom::Rename;
 
enum class [[=EnumFlag]] Toggle: uint8_t {
void setName(const String& newName) noexcept {
Off,
name = newName;
}On
};
 
struct [[=Debug]] Person {
[[=Rename("full name")]]
std::string fullName;
int age;
};
</syntaxhighlight>
 
The annotations have no initial meaning unless some implementations use those annotations to identify some characteristics and features.
{{mono|Main.cpp}}
 
Creating an annotation to generate a specialisation for <code>std::formatter<T></code> is as follows:
<syntaxhighlight lang="cpp">
template <auto V>
import std;
struct Derived {};
 
template <auto V>
import myproject.MyClass;
inline constexpr Derived<V> Derive;
 
inline constexpr struct {} Debug;
using myproject::MyClass;
 
template <typename T>
int main() {
requires (std::meta::has_annotation(^^T, Derive<Debug>))
MyClass me(10, "MyName");
struct std::formatter<T> {
me.setX(15);
// ...
};
 
struct [[=Derive<Debug>]] Point {
std::println("Hello, {}!", me);
int x;
int y;
};
 
int main() {
Point p = Point { .x = 1, .y = 2 };
// prints p = Point { .x = 1, .y = 2 }
std::println("p = {}", p);
}
</syntaxhighlight>
 
== See also ==
* [[C++ standard library]]
* [[C syntax]]
* [[Java syntax]]
* [[C Sharp syntax|C# syntax]]
* [[Rust syntax]]
 
== Notes ==