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%2Fscope.html | |
new repository
Diffstat (limited to 'devdocs/c/language%2Fscope.html')
| -rw-r--r-- | devdocs/c/language%2Fscope.html | 128 |
1 files changed, 128 insertions, 0 deletions
diff --git a/devdocs/c/language%2Fscope.html b/devdocs/c/language%2Fscope.html new file mode 100644 index 00000000..654166df --- /dev/null +++ b/devdocs/c/language%2Fscope.html @@ -0,0 +1,128 @@ + <h1 id="firstHeading" class="firstHeading">Scope</h1> <p>Each <a href="identifier" title="c/language/identifier">identifier</a> that appears in a C program is <i>visible</i> (that is, may be used) only in some possibly discontiguous portion of the source code called its <i>scope</i>.</p> +<p>Within a scope, an identifier may designate more than one entity only if the entities are in different <a href="name_space" title="c/language/name space">name spaces</a>.</p> +<p>C has four kinds of scopes:</p> +<ul> +<li> block scope </li> +<li> file scope </li> +<li> function scope </li> +<li> function prototype scope </li> +</ul> <h3 id="Nested_scopes"> Nested scopes</h3> <p>If two different entities named by the same identifier are in scope at the same time, and they belong to the same <a href="name_space" title="c/language/name space">name space</a>, the scopes are nested (no other form of scope overlap is allowed), and the declaration that appears in the inner scope hides the declaration that appears in the outer scope:</p> +<div class="c source-c"><pre data-language="c">// The name space here is ordinary identifiers. + +int a; // file scope of name a begins here + +void f(void) +{ + int a = 1; // the block scope of the name a begins here; hides file-scope a + { + int a = 2; // the scope of the inner a begins here, outer a is hidden + printf("%d\n", a); // inner a is in scope, prints 2 + } // the block scope of the inner a ends here + printf("%d\n", a); // the outer a is in scope, prints 1 +} // the scope of the outer a ends here + +void g(int a); // name a has function prototype scope; hides file-scope a</pre></div> <h3 id="Block_scope"> Block scope</h3> <p>The scope of any identifier declared inside a <a href="statements#Compound_statements" title="c/language/statements">compound statement</a>, including function bodies, <span class="t-rev-inl t-since-c99"><span>or in any expression, declaration, or statement appearing in <a href="if" title="c/language/if">if</a>, <a href="switch" title="c/language/switch">switch</a>, <a href="for" title="c/language/for">for</a>, <a href="while" title="c/language/while">while</a>, or <a href="do" title="c/language/do">do-while</a> statement</span><span><span class="t-mark-rev t-since-c99">(since C99)</span></span></span>, or within the parameter list of a <a href="function_definition" title="c/language/function definition">function definition</a> begins at the point of declaration and ends at the end of the block or statement in which it was declared.</p> +<div class="c source-c"><pre data-language="c">void f(int n) // scope of the function parameter 'n' begins +{ // the body of the function begins + ++n; // 'n' is in scope and refers to the function parameter +// int n = 2; // error: cannot redeclare identifier in the same scope + for(int n = 0; n<10; ++n) { // scope of loop-local 'n' begins + printf("%d\n", n); // prints 0 1 2 3 4 5 6 7 8 9 + } // scope of the loop-local 'n' ends + // the function parameter 'n' is back in scope + printf("%d\n", n); // prints the value of the parameter +} // scope of function parameter 'n' ends +int a = n; // Error: name 'n' is not in scope</pre></div> <table class="t-rev-begin"> <tr class="t-rev t-since-c99"> +<td> <p>Until C99, selection and iteration statements did not establish their own block scopes (although if a compound statement was used in the statement, it had its usual block scope):</p> +<div class="c source-c"><pre data-language="c">enum {a, b}; +int different(void) +{ + if (sizeof(enum {b, a}) != sizeof(int)) + return a; // a == 1 + return b; // b == 0 in C89, b == 1 in C99 +}</pre></div> </td> <td><span class="t-mark-rev t-since-c99">(since C99)</span></td> +</tr> </table> <p>Block-scope variables have <a href="storage_duration" title="c/language/storage duration">no linkage</a> and <a href="storage_duration" title="c/language/storage duration">automatic storage duration</a> by default. Note that storage duration for non-VLA local variables begins when the block is entered, but until the declaration is seen, the variable is not in scope and cannot be accessed.</p> +<h3 id="File_scope"> File scope</h3> <p>The scope of any identifier declared outside of any block or parameter list begins at the point of declaration and ends at the end of the translation unit.</p> +<div class="c source-c"><pre data-language="c">int i; // scope of i begins +static int g(int a) { return a; } // scope of g begins (note, "a" has block scope) +int main(void) +{ + i = g(2); // i and g are in scope +}</pre></div> <p>File-scope identifiers have <a href="storage_duration" title="c/language/storage duration">external linkage</a> and <a href="storage_duration" title="c/language/storage duration">static storage duration</a> by default.</p> +<h3 id="Function_scope"> Function scope</h3> <p>A <a href="statements#Labels" title="c/language/statements">label (and only a label)</a> declared inside a function is in scope everywhere in that function, in all nested blocks, before and after its own declaration. Note: a label is declared implicitly, by using an otherwise unused identifier before the colon character before any statement.</p> +<div class="c source-c"><pre data-language="c">void f() +{ + { + goto label; // label in scope even though declared later +label:; + } + goto label; // label ignores block scope +} + +void g() +{ + goto label; // error: label not in scope in g() +}</pre></div> <h3 id="Function_prototype_scope"> Function prototype scope</h3> <p>The scope of a name introduced in the parameter list of a <a href="function_declaration" title="c/language/function declaration">function declaration</a> that is not a definition ends at the end of the function <a href="declarations" title="c/language/declarations">declarator</a>.</p> +<div class="c source-c"><pre data-language="c">int f(int n, + int a[n]); // n is in scope and refers to the first parameter</pre></div> <p>Note that if there are multiple or nested declarators in the declaration, the scope ends at the end of the nearest enclosing function declarator:</p> +<div class="c source-c"><pre data-language="c">void f ( // function name 'f' is at file scope + long double f, // the identifier 'f' is now in scope, file-scope 'f' is hidden + char (**a)[10 * sizeof f] // 'f' refers to the first parameter, which is in scope +); + +enum{ n = 3 }; +int (*(*g)(int n))[n]; // the scope of the function parameter 'n' + // ends at the end of its function declarator + // in the array declarator, global n is in scope +// (this declares a pointer to function returning a pointer to an array of 3 int)</pre></div> <h3 id="Point_of_declaration"> Point of declaration</h3> <p>The scope of structure, union, and enumeration tags begins immediately after the appearance of the tag in a type specifier that declares the tag.</p> +<div class="c source-c"><pre data-language="c">struct Node { + struct Node* next; // Node is in scope and refers to this struct +};</pre></div> <p>The scope of enumeration constant begins immediately after the appearance of its defining enumerator in an enumerator list.</p> +<div class="c source-c"><pre data-language="c">enum { x = 12 }; +{ + enum { x = x + 1, // new x is not in scope until the comma, x is initialized to 13 + y = x + 1 // the new enumerator x is now in scope, y is initialized to 14 + }; +}</pre></div> <p>The scope of any other identifier begins just after the end of its declarator and before the initializer, if any:</p> +<div class="c source-c"><pre data-language="c">int x = 2; // scope of the first 'x' begins +{ + int x[x]; // scope of the newly declared x begins after the declarator (x[x]). + // Within the declarator, the outer 'x' is still in scope. + // This declares a VLA array of 2 int. +}</pre></div> <div class="c source-c"><pre data-language="c">unsigned char x = 32; // scope of the outer 'x' begins +{ + unsigned char x = x; + // scope of the inner 'x' begins before the initializer (= x) + // this does not initialize the inner 'x' with the value 32, + // this initializes the inner 'x' with its own, indeterminate, value +} + +unsigned long factorial(unsigned long n) +// declarator ends, 'factorial' is in scope from this point +{ + return n<2 ? 1 : n*factorial(n-1); // recursive call +}</pre></div> <p>As a special case, the scope of a <a href="type" title="c/language/type">type name</a> that is not a declaration of an identifier is considered to begin just after the place within the type name where the identifier would appear were it not omitted.</p> +<h3 id="Notes"> Notes</h3> <p>Prior to C89, identifiers with external linkage had file scope even when introduced within a block, and because of that, a C89 compiler is not required to diagnose the use of an extern identifier that has gone out of scope (such use is undefined behavior).</p> +<p>Local variables within a loop body can hide variables declared in the init clause of a <a href="for" title="c/language/for">for</a> loop in C (their scope is nested), but cannot do that in C++.</p> +<p>Unlike C++, C has no struct scope: names declared within a struct/union/enum declaration are in the same scope as the struct declaration (except that data members are in their own <a href="name_space" title="c/language/name space">member name space</a>):</p> +<div class="c source-c"><pre data-language="c">struct foo { + struct baz {}; + enum color {RED, BLUE}; +}; +struct baz b; // baz is in scope +enum color x = RED; // color and RED are in scope</pre></div> <h3 id="References"> References</h3> <ul> +<li> C17 standard (ISO/IEC 9899:2018): </li> +<ul><li> 6.2.1 Scopes of identifiers (p: 28-29) </li></ul> +<li> C11 standard (ISO/IEC 9899:2011): </li> +<ul><li> 6.2.1 Scopes of identifiers (p: 35-36) </li></ul> +<li> C99 standard (ISO/IEC 9899:1999): </li> +<ul><li> 6.2.1 Scopes of identifiers (p: 29-30) </li></ul> +<li> C89/C90 standard (ISO/IEC 9899:1990): </li> +<ul><li> 3.1.2.1 Scopes of identifiers </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/scope" title="cpp/language/scope">C++ documentation</a></span> for <span class=""><span>Scope</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/scope" class="_attribution-link">https://en.cppreference.com/w/c/language/scope</a> + </p> +</div> |
