summaryrefslogtreecommitdiff
path: root/devdocs/c/language%2Fscope.html
diff options
context:
space:
mode:
authorCraig Jennings <c@cjennings.net>2024-04-07 13:41:34 -0500
committerCraig Jennings <c@cjennings.net>2024-04-07 13:41:34 -0500
commit754bbf7a25a8dda49b5d08ef0d0443bbf5af0e36 (patch)
treef1190704f78f04a2b0b4c977d20fe96a828377f1 /devdocs/c/language%2Fscope.html
new repository
Diffstat (limited to 'devdocs/c/language%2Fscope.html')
-rw-r--r--devdocs/c/language%2Fscope.html128
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&lt;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&lt;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">
+ &copy; 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>