diff options
| author | Craig Jennings <c@cjennings.net> | 2024-04-07 13:41:34 -0500 |
|---|---|---|
| committer | Craig Jennings <c@cjennings.net> | 2024-04-07 13:41:34 -0500 |
| commit | 754bbf7a25a8dda49b5d08ef0d0443bbf5af0e36 (patch) | |
| tree | f1190704f78f04a2b0b4c977d20fe96a828377f1 /devdocs/c/language%2Fdeclarations.html | |
new repository
Diffstat (limited to 'devdocs/c/language%2Fdeclarations.html')
| -rw-r--r-- | devdocs/c/language%2Fdeclarations.html | 142 |
1 files changed, 142 insertions, 0 deletions
diff --git a/devdocs/c/language%2Fdeclarations.html b/devdocs/c/language%2Fdeclarations.html new file mode 100644 index 00000000..f08779ae --- /dev/null +++ b/devdocs/c/language%2Fdeclarations.html @@ -0,0 +1,142 @@ + <h1 id="firstHeading" class="firstHeading">Declarations</h1> <p>A <i>declaration</i> is a C language construct that introduces one or more <a href="identifier" title="c/language/identifier">identifiers</a> into the program and specifies their meaning and properties.</p> +<p>Declarations may appear in any scope. Each declaration ends with a semicolon (just like <a href="statements" title="c/language/statements">a statement</a>) and consists of <span class="t-rev-inl t-until-c23"><span>two</span><span><span class="t-mark-rev t-until-c23">(until C23)</span></span></span><span class="t-rev-inl t-since-c23"><span>three</span><span><span class="t-mark-rev t-since-c23">(since C23)</span></span></span> distinct parts:</p> +<table class="t-sdsc-begin"> <tr class="t-sdsc"> <td> <span class="t-spar">specifiers-and-qualifiers</span> <span class="t-spar">declarators-and-initializers</span><span class="t-mark">(optional)</span> <code>;</code> </td> <td> (1) </td> <td class="t-sdsc-nopad"> </td> +</tr> <tr class="t-sdsc"> <td> <span class="t-spar">attr-spec-seq</span> <span class="t-spar">specifiers-and-qualifiers</span> <span class="t-spar">declarators-and-initializers</span> <code>;</code> </td> <td> (2) </td> <td> <span class="t-mark-rev t-since-c23">(since C23)</span> </td> +</tr> <tr class="t-sdsc"> <td> <span class="t-spar">attr-spec-seq</span> <code>;</code> </td> <td> (3) </td> <td> <span class="t-mark-rev t-since-c23">(since C23)</span> </td> +</tr> +</table> <p>where</p> +<table class="t-par-begin"> <tr class="t-par"> <td> <span class="t-spar">specifiers-and-qualifiers</span> </td> <td> - </td> <td> whitespace-separated list of, in any order, <ul> +<li> type specifiers: </li> +<ul> +<li> <code>void</code> </li> +<li> the name of an <a href="arithmetic_types" title="c/language/arithmetic types">arithmetic type</a> </li> +<li> the name of an <a href="atomic" title="c/language/atomic">atomic type</a> </li> +<li> a name earlier introduced by a <a href="typedef" title="c/language/typedef">typedef</a> declaration </li> +<li> <a href="struct" title="c/language/struct"><code>struct</code></a>, <a href="union" title="c/language/union"><code>union</code></a>, or <a href="enum" title="c/language/enum"><code>enum</code></a> specifier </li> +<li> a <a href="typeof" title="c/language/typeof">typeof</a> specifier <span class="t-mark-rev t-since-c23">(since C23)</span> </li> +</ul> +<li> zero or one storage-class specifiers: <a href="typedef" title="c/language/typedef"><code>typedef</code></a>, <a href="constexpr" title="c/language/constexpr"><code>constexpr</code></a>, <a href="auto" title="c/language/auto"><code>auto</code></a>, <a href="storage_duration" title="c/language/storage duration"><code>register</code>, <code>static</code>, <code>extern</code>, <code>_Thread_local</code></a> </li> +<li> zero or more type qualifiers: <a href="const" title="c/language/const"><code>const</code></a>, <a href="volatile" title="c/language/volatile"><code>volatile</code></a>, <a href="restrict" title="c/language/restrict"><code>restrict</code></a>, <a href="atomic" title="c/language/atomic"><code>_Atomic</code></a> </li> +<li> (only when declaring functions), zero or more function specifiers: <a href="inline" title="c/language/inline"><code>inline</code></a>, <a href="_noreturn" title="c/language/ Noreturn"><code>_Noreturn</code></a> </li> +<li> zero or more alignment specifiers: <a href="_alignas" title="c/language/ Alignas"><code>_Alignas</code></a> </li> +</ul> </td> +</tr> <tr class="t-par"> <td> <span class="t-spar">declarators-and-initializers</span> </td> <td> - </td> <td> comma-separated list of <span class="t-spar">declarators</span> (each declarator provides additional type information and/or the identifier to declare). Declarators may be accompanied by <a href="initialization" title="c/language/initialization">initializers</a>. The <a href="enum" title="c/language/enum">enum</a>, <a href="struct" title="c/language/struct">struct</a>, and <a href="union" title="c/language/union">union</a> declarations may omit <span class="t-spar">declarators</span>, in which case they only introduce the enumeration constants and/or tags. </td> +</tr> <tr class="t-par"> <td> <span class="t-spar">attr-spec-seq</span> </td> <td> - </td> <td> <span class="t-mark-rev t-since-c23">(C23)</span>optional list of <a href="attributes" title="c/language/attributes">attributes</a>, applied to the declared entities, or forms an attribute declaration if appears alone. </td> +</tr> +</table> <div class="t-li1"> +<span class="t-li">1-2)</span> Simple declaration. Introduces one or more identifiers which denotes objects, functions, struct/union/enum tags, typedefs, or enumeration constants.</div> <div class="t-li1"> +<span class="t-li">3)</span> Attribute declaration. Does not declares any identifier, and has implementation-defined meaning if the meaning is not specified by the standard.</div> <p>For example,</p> +<div class="c source-c"><pre data-language="c">int a, *b=NULL; // "int" is the type specifier, + // "a" is a declarator + // "*b" is a declarator and NULL is its initializer +const int *f(void); // "int" is the type specifier + // "const" is the type qualifier + // "*f(void)" is the declarator +enum COLOR {RED, GREEN, BLUE} c; // "enum COLOR {RED, GREEN, BLUE}" is the type specifier + // "c" is the declarator</pre></div> <p>The type of each identifier introduced in a declaration is determined by a combination of the type specified by the <span class="t-spar">type specifier</span> and the type modifications applied by its <span class="t-spar">declarator</span>. <span class="t-rev-inl t-since-c23"><span>The type of a variable might also be inferred if <code>auto</code> specifier is used.</span><span><span class="t-mark-rev t-since-c23">(since C23)</span></span></span></p> +<p><a href="attributes" title="c/language/attributes">Attributes</a><span class="t-mark-rev t-since-c23">(since C23)</span> may appear in <span class="t-spar">specifiers-and-qualifiers</span>, in which case they apply to the type determined by the preceding specifiers.</p> +<h3 id="Declarators"> Declarators</h3> <p>Each declarator is one of the following:</p> +<table class="t-sdsc-begin"> <tr class="t-sdsc"> <td> <span class="t-spar">identifier</span> <span class="t-spar">attr-spec-seq</span><span class="t-mark">(optional)</span> </td> <td> (1) </td> <td class="t-sdsc-nopad"> </td> +</tr> <tr class="t-sdsc"> <td> <code>(</code> <span class="t-spar">declarator</span> <code>)</code> </td> <td> (2) </td> <td class="t-sdsc-nopad"> </td> +</tr> <tr class="t-sdsc"> <td> <code>*</code> <span class="t-spar">attr-spec-seq</span><span class="t-mark">(optional)</span> <span class="t-spar">qualifiers</span><span class="t-mark">(optional)</span> <span class="t-spar">declarator</span> </td> <td> (3) </td> <td class="t-sdsc-nopad"> </td> +</tr> <tr class="t-sdsc"> <td> <span class="t-spar">noptr-declarator</span> <code>[</code> <code>static</code><span class="t-mark">(optional)</span> <span class="t-spar">qualifiers</span><span class="t-mark">(optional)</span> <span class="t-spar">expression</span> <code>]</code> <p><span class="t-spar">noptr-declarator</span> <code>[</code> <span class="t-spar">qualifiers</span><span class="t-mark">(optional)</span> <code>*</code> <code>]</code></p> +</td> <td> (4) </td> <td class="t-sdsc-nopad"> </td> +</tr> <tr class="t-sdsc"> <td> <span class="t-spar">noptr-declarator</span> <code>(</code> <span class="t-spar">parameters-or-identifiers</span> <code>)</code> </td> <td> (5) </td> <td class="t-sdsc-nopad"> </td> +</tr> +</table> <div class="t-li1"> +<span class="t-li">1)</span> the identifier that this declarator introduces.</div> <div class="t-li1"> +<span class="t-li">2)</span> any declarator may be enclosed in parentheses; this is required to introduce pointers to arrays and pointers to functions.</div> <div class="t-li1"> +<span class="t-li">3)</span> <a href="pointer" title="c/language/pointer">pointer declarator</a>: the declaration <code>S * cvr D</code>; declares <code>D</code> as a <span class="t-spar">cvr</span>-qualified pointer to the type determined by <code>S</code>.</div> <div class="t-li1"> +<span class="t-li">4)</span> <a href="array" title="c/language/array">array declarator</a>: the declaration <code>S D[N]</code> declares <code>D</code> as an array of <code>N</code> objects of the type determined by <code>S</code>. <span class="t-spar">noptr-declarator</span> is any other declarator except unparenthesized pointer declarator.</div> <div class="t-li1"> +<span class="t-li">5)</span> <a href="function_declaration" title="c/language/function declaration">function declarator</a>: the declaration <code>S D(params)</code> declared <code>D</code> as a function taking the parameters <code>params</code> and returning <code>S</code>. <span class="t-spar">noptr-declarator</span> is any other declarator except unparenthesized pointer declarator.</div> <p>The reasoning behind this syntax is that when the identifier declared by the declarator appears in an expression of the same form as the declarator, it would have the type specified by the type specifier sequence.</p> +<div class="c source-c"><pre data-language="c">struct C { + int member; // "int" is the type specifier + // "member" is the declarator +} obj, *pObj = &obj; +// "struct C { int member; }" is the type specifier +// declarator "obj" defines an object of type struct C +// declarator "*pObj" declares a pointer to C, +// initializer "= &obj" provides the initial value for that pointer + +int a = 1, *p = NULL, f(void), (*pf)(double); +// the type specifier is "int" +// declarator "a" defines an object of type int +// initializer "=1" provides its initial value +// declarator "*p" defines an object of type pointer to int +// initializer "=NULL" provides its initial value +// declarator "f(void)" declares a function taking void and returning int +// declarator "(*pf)(double)" defines an object of type pointer +// to function taking double and returning int + +int (*(*foo)(double))[3] = NULL; +// the type specifier is int +// 1. declarator "(*(*foo)(double))[3]" is an array declarator: +// the type declared is "/nested declarator/ array of 3 int" +// 2. the nested declarator is "*(*foo)(double))", which is a pointer declarator +// the type declared is "/nested declarator/ pointer to array of 3 int" +// 3. the nested declarator is "(*foo)(double)", which is a function declarator +// the type declared is "/nested declarator/ function taking double and returning +// pointer to array of 3 int" +// 4. the nested declarator is "(*foo)" which is a (parenthesized, as required by +// function declarator syntax) pointer declarator. +// the type declared is "/nested declarator/ pointer to function taking double +// and returning pointer to array of 3 int" +// 5. the nested declarator is "foo", which is an identifier. +// The declaration introduces the identifier "foo" to refer to an object of type +// "pointer to function taking double and returning pointer to array of 3 int" +// The initializer "= NULL" provides the initial value of this pointer. + +// If "foo" is used in an expression of the form of the declarator, its type would be +// int. +int x = (*(*foo)(1.2))[0];</pre></div> <p>The end of every declarator that is not part of another declarator is a <a href="eval_order" title="c/language/eval order">sequence point</a>.</p> +<p>In all cases, <span class="t-spar">attr-spec-seq</span> is an optional sequence of <a href="attributes" title="c/language/attributes">attributes</a><span class="t-mark-rev t-since-c23">(since C23)</span>. When appearing immediately after the identifier, it applies to the object or function being declared.</p> +<h3 id="Definitions"> Definitions</h3> <p>A <i>definition</i> is a declaration that provides all information about the identifiers it declares.</p> +<p>Every declaration of an <a href="enum" title="c/language/enum">enum</a> or a <a href="typedef" title="c/language/typedef">typedef</a> is a definition.</p> +<p>For functions, a declaration that includes the function body is a <a href="function_definition" title="c/language/function definition">function definition</a>:</p> +<div class="c source-c"><pre data-language="c">int foo(double); // declaration +int foo(double x){ return x; } // definition</pre></div> <p>For objects, a declaration that allocates storage (<a href="storage_duration" title="c/language/storage duration">automatic or static</a>, but not extern) is a definition, while a declaration that does not allocate storage (<a href="extern" title="c/language/extern">external declaration</a>) is not.</p> +<div class="c source-c"><pre data-language="c">extern int n; // declaration +int n = 10; // definition</pre></div> <p>For <a href="struct" title="c/language/struct">structs</a> and <a href="union" title="c/language/union">unions</a>, declarations that specify the list of members are definitions:</p> +<div class="c source-c"><pre data-language="c">struct X; // declaration +struct X { int n; }; // definition</pre></div> <h3 id="Redeclaration"> Redeclaration</h3> <p>A declaration cannot introduce an identifier if another declaration for the same identifier in the same <a href="scope" title="c/language/scope">scope</a> appears earlier, except that</p> +<ul><li> Declarations of objects <a href="storage_duration" title="c/language/storage duration">with linkage</a> (external or internal) can be repeated: </li></ul> <div class="c source-c"><pre data-language="c">extern int x; +int x = 10; // OK +extern int x; // OK + +static int n; +static int n = 10; // OK +static int n; // OK</pre></div> <ul><li> Non-VLA <a href="typedef" title="c/language/typedef">typedef</a> can be repeated as long as it names the same type: </li></ul> <div class="c source-c"><pre data-language="c">typedef int int_t; +typedef int int_t; // OK</pre></div> <ul><li> <a href="struct" title="c/language/struct">struct</a> and <a href="union" title="c/language/union">union</a> declarations can be repeated: </li></ul> <div class="c source-c"><pre data-language="c">struct X; +struct X { int n; }; +struct X;</pre></div> <p>These rules simplify the use of header files.</p> +<h3 id="Notes"> Notes</h3> <table class="t-rev-begin"> <tr class="t-rev t-until-c99"> +<td> <p>In C89, declarations within any <a href="statements#Compound_statements" title="c/language/statements">compound statement</a> (block scope) must appear in the beginning of the block, before any <a href="statements" title="c/language/statements">statements</a>.</p> +<p>Also, in C89, functions returning <code>int</code> may be implicitly declared by the <a href="operator_other#Function_call" title="c/language/operator other">function call operator</a> and function parameters of type <code>int</code> do not have to be declared when using old-style <a href="function_definition" title="c/language/function definition">function definitions</a>.</p> +</td> <td><span class="t-mark-rev t-until-c99">(until C99)</span></td> +</tr> </table> <p>Empty declarators are prohibited; a simple declaration must have at least one declarator or declare at least one struct/union/enum tag, or introduce at least one enumeration constant.</p> +<table class="t-rev-begin"> <tr class="t-rev t-since-c99"> +<td> <p>If any part of a declarator is a <a href="array" title="c/language/array">variable-length array</a> (VLA) declarator, the entire declarator's type is known as "variably-modified type". Types defined from variably-modified types are also variably modified (VM).</p> +<p>Declarations of any variably-modified types may appear only at <a href="scope" title="c/language/scope">block scope</a> or function prototype scope and cannot be members of structs or unions. Although VLA can only have automatic or allocated <a href="storage_duration" title="c/language/storage duration">storage duration</a>, a VM type such as a pointer to a VLA may be static. There are other restrictions on the use of VM types, see <a href="goto" title="c/language/goto">goto</a>, <a href="switch" title="c/language/switch">switch</a>. <code><a href="../program/longjmp" title="c/program/longjmp">longjmp</a></code></p> +</td> <td><span class="t-mark-rev t-since-c99">(since C99)</span></td> +</tr> </table> <table class="t-rev-begin"> <tr class="t-rev t-since-c11"> +<td> <p><a href="_static_assert" title="c/language/ Static assert">static_asserts</a> are considered to be declarations from the point of view of the C grammar (so that they may appear anywhere a declaration may appear), but they do not introduce any identifiers and do not follow the declaration syntax.</p> +</td> <td><span class="t-mark-rev t-since-c11">(since C11)</span></td> +</tr> </table> <table class="t-rev-begin"> <tr class="t-rev t-since-c23"> +<td> <p><a href="attributes" title="c/language/attributes">Attribute</a> declarations are also considered to be declarations (so that they may appear anywhere a declaration may appear), but they do not introduce any identifiers. A single <code>;</code> without <span class="t-spar">attr-spec-seq</span> is not an attribute declaration, but a statement.</p> +</td> <td><span class="t-mark-rev t-since-c23">(since C23)</span></td> +</tr> </table> <h3 id="References"> References</h3> <ul> +<li> C17 standard (ISO/IEC 9899:2018): </li> +<ul><li> 6.7 Declarations (p: 78-105) </li></ul> +<li> C11 standard (ISO/IEC 9899:2011): </li> +<ul><li> 6.7 Declarations (p: 108-145) </li></ul> +<li> C99 standard (ISO/IEC 9899:1999): </li> +<ul><li> 6.7 Declarations (p: 97-130) </li></ul> +<li> C89/C90 standard (ISO/IEC 9899:1990): </li> +<ul><li> 3.5 Declarations </li></ul> +</ul> <h3 id="See_also"> See also</h3> <table class="t-dsc-begin"> <tr class="t-dsc"> <td colspan="2"> <span><a href="https://en.cppreference.com/w/cpp/language/declarations" title="cpp/language/declarations">C++ documentation</a></span> for <span class=""><span>Declarations</span></span> </td> +</tr> </table> <div class="_attribution"> + <p class="_attribution-p"> + © cppreference.com<br>Licensed under the Creative Commons Attribution-ShareAlike Unported License v3.0.<br> + <a href="https://en.cppreference.com/w/c/language/declarations" class="_attribution-link">https://en.cppreference.com/w/c/language/declarations</a> + </p> +</div> |
