Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > comp.lang.c > #75880 > unrolled thread
| Started by | Jon Rossen <jonr17@comcast.net> |
|---|---|
| First post | 2015-11-12 13:32 -0800 |
| Last post | 2015-11-15 21:17 -0800 |
| Articles | 20 on this page of 22 — 7 participants |
Back to article view | Back to comp.lang.c
A question on variable scope, coming from a relative beginner Jon Rossen <jonr17@comcast.net> - 2015-11-12 13:32 -0800
Re: A question on variable scope, coming from a relative beginner John Gordon <gordon@panix.com> - 2015-11-12 21:57 +0000
Re: A question on variable scope, coming from a relative beginner Jon Rossen <jonr17@comcast.net> - 2015-11-12 16:06 -0800
Re: A question on variable scope, coming from a relative beginner James Kuyper <jameskuyper@verizon.net> - 2015-11-12 19:33 -0500
Re: A question on variable scope, coming from a relative beginner Jon Rossen <jonr17@comcast.net> - 2015-11-12 20:22 -0800
Re: A question on variable scope, coming from a relative beginner James Kuyper <jameskuyper@verizon.net> - 2015-11-13 08:08 -0500
Re: A question on variable scope, coming from a relative beginner Richard Heathfield <rjh@cpax.org.uk> - 2015-11-12 21:57 +0000
Re: A question on variable scope, coming from a relative beginner Jon Rossen <jonr17@comcast.net> - 2015-11-12 18:47 -0800
Re: A question on variable scope, coming from a relative beginner James Kuyper <jameskuyper@verizon.net> - 2015-11-12 22:19 -0500
Re: A question on variable scope, coming from a relative beginner Jon Rossen <jonr17@comcast.net> - 2015-11-12 22:05 -0800
Re: A question on variable scope, coming from a relative beginner Richard Heathfield <rjh@cpax.org.uk> - 2015-11-13 07:10 +0000
Re: A question on variable scope, coming from a relative beginner James Kuyper <jameskuyper@verizon.net> - 2015-11-13 08:33 -0500
Re: A question on variable scope, coming from a relative beginner Tim Rentsch <txr@alumni.caltech.edu> - 2015-11-13 12:24 -0800
Re: A question on variable scope, coming from a relative beginner Keith Thompson <kst-u@mib.org> - 2015-11-14 11:58 -0800
Re: A question on variable scope, coming from a relative beginner James Kuyper <jameskuyper@verizon.net> - 2015-11-14 15:27 -0500
Re: A question on variable scope, coming from a relative beginner Malcolm McLean <malcolm.mclean5@btinternet.com> - 2015-11-12 14:00 -0800
Re: A question on variable scope, coming from a relative beginner Richard Heathfield <rjh@cpax.org.uk> - 2015-11-12 23:55 +0000
Re: A question on variable scope, coming from a relative beginner Keith Thompson <kst-u@mib.org> - 2015-11-12 17:11 -0800
Re: A question on variable scope, coming from a relative beginner Jon Rossen <jonr17@comcast.net> - 2015-11-12 20:39 -0800
Re: A question on variable scope, coming from a relative beginner Jon Rossen <jonr17@comcast.net> - 2015-11-12 20:38 -0800
Re: A question on variable scope, coming from a relative beginner Keith Thompson <kst-u@mib.org> - 2015-11-12 22:13 -0800
Re: A question on variable scope, coming from a relative beginner Jon Rossen <jonr17@comcast.net> - 2015-11-15 21:17 -0800
Page 1 of 2 [1] 2 Next page →
| From | Jon Rossen <jonr17@comcast.net> |
|---|---|
| Date | 2015-11-12 13:32 -0800 |
| Subject | A question on variable scope, coming from a relative beginner |
| Message-ID | <n230ii$pmi$1@news.albasani.net> |
Hi all, I'm fairly new to programming and have a question on the C
language with regards to variable scope, compilers and the 'extern'
keyword. I'm using a couple of books that seem to have info that is not
in keeping with my results. Here's a simple little trivial code example
that illustrates the question:
#include <stdio.h>
int x = 999;
void print_value(void);
int main(void)
{
extern int x; // This entire statement is not necessary to
// get the proper results, why??
printf("%d\n", x);
print_value();
return 0;
}
void print_value(void)
{
extern int x; // This obviously is
printf("%d\n", x);
}
Result: 999
999
In this example from my book, I'm seeing that the use of extern is not
necessary in main(), the book says that it is. In other words you can
omit the 'extern int x' statement completely, and main() can still
access the externally defined variable int x that has been initialized
to 999. But it's sort of odd in that you can also use 'int x' and
initialize it to something say 'int x = 9' in main() and the compiler
doesn't squawk. It's not odd on it's own merits since main() is a
function and can have it's own local variables. But if that's the case,
why don't you then have to use 'intern int x' to access the externally
defined variable?
Is main() treated as a special case with regards to this (compared to
other functions)? It seems asymmetrical to some degree: On one hand
there is data encapsulation going on in main() in that it can have it's
own version of int x, the compiler won't complain that you are
redefining an already defined variable. BUT, AT THE SAME TIME, you don't
have to use the declaration extern int x to 'reach out' and access the
external variable, if that's what you want to do Why is that? Does it
depend on the compiler? Is this something that has changed over the
years (my books could be out of date).
Thanks for any pointers (no pun intended) :-)
jonR
[toc] | [next] | [standalone]
| From | John Gordon <gordon@panix.com> |
|---|---|
| Date | 2015-11-12 21:57 +0000 |
| Message-ID | <n231vv$kkj$1@reader1.panix.com> |
| In reply to | #75880 |
In <n230ii$pmi$1@news.albasani.net> Jon Rossen <jonr17@comcast.net> writes:
> In this example from my book, I'm seeing that the use of extern is not
> necessary in main(), the book says that it is. In other words you can
Did the example put the print_value() function in a separate file?
The usual purpose of the 'extern' keyword is to access a variable that
is declared in a separate compilation unit (i.e. a separate c file).
--
John Gordon A is for Amy, who fell down the stairs
gordon@panix.com B is for Basil, assaulted by bears
-- Edward Gorey, "The Gashlycrumb Tinies"
[toc] | [prev] | [next] | [standalone]
| From | Jon Rossen <jonr17@comcast.net> |
|---|---|
| Date | 2015-11-12 16:06 -0800 |
| Message-ID | <n239hn$962$1@news.albasani.net> |
| In reply to | #75882 |
On 11/12/2015 1:57 PM, John Gordon wrote: > In <n230ii$pmi$1@news.albasani.net> Jon Rossen <jonr17@comcast.net> writes: > >> In this example from my book, I'm seeing that the use of extern is not >> necessary in main(), the book says that it is. In other words you can > > Did the example put the print_value() function in a separate file? > > The usual purpose of the 'extern' keyword is to access a variable that > is declared in a separate compilation unit (i.e. a separate c file). > Yes, I realize that is one of the purposes of extern (separate module), but in this example we are just talking about one file. -jonR
[toc] | [prev] | [next] | [standalone]
| From | James Kuyper <jameskuyper@verizon.net> |
|---|---|
| Date | 2015-11-12 19:33 -0500 |
| Message-ID | <n23avr$vq4$1@dont-email.me> |
| In reply to | #75896 |
On 11/12/2015 07:06 PM, Jon Rossen wrote: > On 11/12/2015 1:57 PM, John Gordon wrote: ... >> The usual purpose of the 'extern' keyword is to access a variable that >> is declared in a separate compilation unit (i.e. a separate c file). >> > > Yes, I realize that is one of the purposes of extern (separate module), What other uses do you think 'extern' has? -- James Kuyper
[toc] | [prev] | [next] | [standalone]
| From | Jon Rossen <jonr17@comcast.net> |
|---|---|
| Date | 2015-11-12 20:22 -0800 |
| Message-ID | <n23oio$l5a$1@news.albasani.net> |
| In reply to | #75900 |
On 11/12/2015 4:33 PM, James Kuyper wrote: > On 11/12/2015 07:06 PM, Jon Rossen wrote: >> On 11/12/2015 1:57 PM, John Gordon wrote: > ... >>> The usual purpose of the 'extern' keyword is to access a variable that >>> is declared in a separate compilation unit (i.e. a separate c file). >>> >> >> Yes, I realize that is one of the purposes of extern (separate module), > > What other uses do you think 'extern' has? > Let me go out on a limb here: Probably none, I was just expressing this in an imprecise fashion. For some reason you didn't want to just correct me but seem to want to go through some sort of Socratic Method kind of deal. That's fine, and I appreciate your assistance but why not just take the direct route? :-)
[toc] | [prev] | [next] | [standalone]
| From | James Kuyper <jameskuyper@verizon.net> |
|---|---|
| Date | 2015-11-13 08:08 -0500 |
| Message-ID | <n24n7f$vb3$1@dont-email.me> |
| In reply to | #75921 |
On 11/12/2015 11:22 PM, Jon Rossen wrote: > On 11/12/2015 4:33 PM, James Kuyper wrote: >> On 11/12/2015 07:06 PM, Jon Rossen wrote: >>> On 11/12/2015 1:57 PM, John Gordon wrote: >> ... >>>> The usual purpose of the 'extern' keyword is to access a variable that >>>> is declared in a separate compilation unit (i.e. a separate c file). >>>> >>> >>> Yes, I realize that is one of the purposes of extern (separate module), >> >> What other uses do you think 'extern' has? >> > > Let me go out on a limb here: Probably none, I was just expressing this > in an imprecise fashion. ... Correct. > ... For some reason you didn't want to just > correct me but seem to want to go through some sort of Socratic Method > kind of deal. That's fine, and I appreciate your assistance > but why not just take the direct route? :-) Because I wanted to figure out what your misunderstanding was, before I attempted to correct it. It seemed pretty clear from your original message that there was something you were misunderstanding, but it wasn't clear to me what it was. -- James Kuyper
[toc] | [prev] | [next] | [standalone]
| From | Richard Heathfield <rjh@cpax.org.uk> |
|---|---|
| Date | 2015-11-12 21:57 +0000 |
| Message-ID | <n231rp$qc0$1@dont-email.me> |
| In reply to | #75880 |
On 12/11/15 21:32, Jon Rossen wrote:
> Hi all, I'm fairly new to programming and have a question on the C
> language with regards to variable scope, compilers and the 'extern'
> keyword. I'm using a couple of books that seem to have info that is not
> in keeping with my results. Here's a simple little trivial code example
> that illustrates the question:
>
> #include <stdio.h>
>
> int x = 999;
This is a definition that is outside any function. Because of that, the
name 'x' now has file scope (that is, the name 'x' is visible to all the
code in this file from this point onwards) and (because it isn't
static-qualified) it also has external linkage. That is, access to x is
possible from other C modules that are linked to this one, provided they
declare x's existence using:
extern int x;
Such a declaration is unnecessary (but legal) within the file where x
itself is defined...
> void print_value(void);
>
> int main(void)
> {
...such as here.
> extern int x; // This entire statement is not necessary to
> // get the proper results, why??
Because main() is in the same file as the definition of x. There's
nothing special about main() in this regard, no "magic" going on. You
don't need the extern int x; here, not because it's main() but because
*all* the functions that appear below
int x = 999;
can see it, since it's defined outside any function. The main() function
is one such function, but there could easily be others.
>
> printf("%d\n", x);
> print_value();
>
> return 0;
> }
>
> void print_value(void)
> {
> extern int x; // This obviously is
No, you don't need it here either.
> printf("%d\n", x);
> }
>
> Result: 999
> 999
>
> In this example from my book, I'm seeing that the use of extern is not
> necessary in main(), the book says that it is.
<sigh> What's the book?
> In other words you can
> omit the 'extern int x' statement completely, and main() can still
> access the externally defined variable int x that has been initialized
> to 999.
So can all the other functions in that same file - at least, the ones
that appear lexically *after* the definition.
> But it's sort of odd in that you can also use 'int x' and
> initialize it to something say 'int x = 9' in main() and the compiler
> doesn't squawk.
That's a *different* x. (Horrid, huh?) It's called "shadowing", and this
new local x 'trumps' the file scope x for as long as the local x is in
scope, leading to all kinds of confusion. It's just not funny. That's
one of several excellent reasons to avoid file scope objects as much as
possible.
> Is main() treated as a special case with regards to this (compared to
> other functions)?
Nope.
--
Richard Heathfield
Email: rjh at cpax dot org dot uk
"Usenet is a strange place" - dmr 29 July 1999
Sig line 4 vacant - apply within
[toc] | [prev] | [next] | [standalone]
| From | Jon Rossen <jonr17@comcast.net> |
|---|---|
| Date | 2015-11-12 18:47 -0800 |
| Message-ID | <n23j1m$cad$1@news.albasani.net> |
| In reply to | #75883 |
Richard,
Thanks MUCH for breaking down my posting and responding to each of the
sections. I really appreciate it. I was confused by my book (stating
that extern is needed in this example) and by myself. For some reason
that I can't explain, I thought that the other function (print_value())
*needed* to have it's extern statement. It must have been due to a
typo, perhaps by putting the definition of int x inside made or
something..who knows. Generally, I fully understand your explanations...
Some minor comments/responses inline below... thx, jonR
On 11/12/2015 1:57 PM, Richard Heathfield wrote:
> On 12/11/15 21:32, Jon Rossen wrote:
>> Hi all, I'm fairly new to programming and have a question on the C
>> language with regards to variable scope, compilers and the 'extern'
>> keyword. I'm using a couple of books that seem to have info that is not
>> in keeping with my results. Here's a simple little trivial code example
>> that illustrates the question:
>>
>> #include <stdio.h>
>>
>> int x = 999;
>
> This is a definition that is outside any function. Because of that, the
> name 'x' now has file scope (that is, the name 'x' is visible to all the
> code in this file from this point onwards) and (because it isn't
> static-qualified) it also has external linkage. That is, access to x is
> possible from other C modules that are linked to this one, provided they
> declare x's existence using:
>
> extern int x;
>
> Such a declaration is unnecessary (but legal) within the file where x
> itself is defined...
Got it! unecessary (but legal). It is not destructive in any way.
Might it be at least a little helpful as a notification method as it
tells the reader of the code that we're using an external variable? In
other words, it just underscores it by mentioning in explicitly.
I am familiar with the need to use extern in *other* modules, and the
use of static to eliminate external linkage functionality. However, I
had two more questions re: some of this. I was going to ask this in
another posting but I'll do it here since you mentioned it.
1. Use of static to make a variable unusable by other modules: I get
how this works with regards to the mechanics, buy not *why*. Let me
explain: I understand what static does when used with a local variable;
it allows the variable to retain it's value through multiple function
calls. Let's say you have a function that does a page count or
something such as that. Ok, I get all of this. But why then does the
static keyword in front of a variable defined outside a function make
that variable unusable by other modules? I don't see how this
by-product of the keyword is related to the example I just illustrated
with local variables. It seems like a programming non-sequitur. If
they are related conceptually, I don't see it. Is there some relation
between these two things? Meaning: 1) Allowing a local variable to
retain its value & 2) inhibiting a variable defined outside a function
from being used in another module. How are these 2 things related?
2. Ok, using extern in other modules to access the originally defined
variable. I understand this and how extern allows you to declare the
existence of a previously *defined* variable. However, I'm seeing
inconsistencies in the need to use extern for this purpose. I'm
referring to differences between 3 different compilers that are in 3
different IDEs that I'm using: Visual Studio 2010, Code::Blocks and
Xcode (yes, I'm working on Objective-C too). In both of these examples
I've created a bare-bones C project with two modules. So, I've got
main.c and 2.c. I have a variable defined in main.c that's not inside
any function; let's call it int foo. In module 2.c, in theory I am
supposed to use 'extern int foo' in order to access that variable.
However, in Visual Studio and Code::Blocks I don't have to use 'extern'.
All I have to do is use the statement 'int foo' at the beginning of
the module, before any dependent functions and I can access the
originally defined int foo in main.c (the first module). The use of
extern is *not* necessary. I get the correct results. In Xcode it is
necessary, and not using extern causes linker errors...duplicate symbols
or something to that extent. That makes sense as technically I'm
incorrectly declaring int foo two times by not using extern for the
second time. So, why do Visual Studio and Code:Blocks allow me to do
this, I get the correct result, and there are no linker errors for both
of these IDEs?
>
>> void print_value(void);
>>
>> int main(void)
>> {
>
> ...such as here.
>
>> extern int x; // This entire statement is not necessary to
>> // get the proper results, why??
>
> Because main() is in the same file as the definition of x. There's
> nothing special about main() in this regard, no "magic" going on. You
> don't need the extern int x; here, not because it's main() but because
> *all* the functions that appear below
>
> int x = 999;
>
> can see it, since it's defined outside any function. The main() function
> is one such function, but there could easily be others.
>
OK. Got it.
>>
>> printf("%d\n", x);
>> print_value();
>>
>> return 0;
>> }
>>
>> void print_value(void)
>> {
>> extern int x; // This obviously is
>
> No, you don't need it here either.
Yep. Don't know why I thought otherwise. As I stated earlier probably
brain freeze on my part.
>
>> printf("%d\n", x);
>> }
>>
>> Result: 999
>> 999
>>
>> In this example from my book, I'm seeing that the use of extern is not
>> necessary in main(), the book says that it is.
>
> <sigh> What's the book?
The book is 'Teach Yourself C in 21 Days', Sams Publishing.
>
>> In other words you can
>> omit the 'extern int x' statement completely, and main() can still
>> access the externally defined variable int x that has been initialized
>> to 999.
>
> So can all the other functions in that same file - at least, the ones
> that appear lexically *after* the definition.
Yep.
>
>
>> But it's sort of odd in that you can also use 'int x' and
>> initialize it to something say 'int x = 9' in main() and the compiler
>> doesn't squawk.
>
> That's a *different* x. (Horrid, huh?) It's called "shadowing", and this
> new local x 'trumps' the file scope x for as long as the local x is in
> scope, leading to all kinds of confusion. It's just not funny. That's
> one of several excellent reasons to avoid file scope objects as much as
> possible.
Yes, I already knew what was going on here with that ('shadowing'). I
wasn't saying it was odd because you could do it, but because it was
'juxtaposed' (seemingly) with my incorrect notion of what extern was
supposed to do or how it was needed or not. It may be bad practice
because it creates confusion but it serves to be a good learning point.
Sometimes seeing bad things helps you understand things.
>
>> Is main() treated as a special case with regards to this (compared to
>> other functions)?
>
> Nope.
>
Yep, got it. This is good to know. I was just asking about his as some
sort of explanation for things that I was seeing but wasn't expecting.
[toc] | [prev] | [next] | [standalone]
| From | James Kuyper <jameskuyper@verizon.net> |
|---|---|
| Date | 2015-11-12 22:19 -0500 |
| Message-ID | <n23knc$l07$1@dont-email.me> |
| In reply to | #75916 |
On 11/12/2015 09:47 PM, Jon Rossen wrote: ... > 1. Use of static to make a variable unusable by other modules: I get > how this works with regards to the mechanics, buy not *why*. Let me > explain: I understand what static does when used with a local variable; > it allows the variable to retain it's value through multiple function > calls. Let's say you have a function that does a page count or > something such as that. Ok, I get all of this. But why then does the > static keyword in front of a variable defined outside a function make > that variable unusable by other modules? I don't see how this > by-product of the keyword is related to the example I just illustrated > with local variables. It seems like a programming non-sequitur. Don't worry about that - it just means that you're correctly perceiving things. The static keyword has been given three entirely unrelated meanings, depending upon the context: 1. When applied to the definition of a file scope object or function, it gives that object or function's identifier internal linkage. (6.2.2p3) 2. When applied to the definition of a block scope object, it gives that object static storage duration.(6.2.4p3) 3. When used inside the leading dimension of a function parameter declared as if it were an array, as in the following example: void func(int param[static 16]) it makes it undefined behavior to call func() with a pointer to that does not give access to an array containing at least 16 items. (6.7.6.3p7). This is a relatively new meaning, introduced in C99. On comp.std.c, when someone suggests that a new feature be added to C, there will often be someone who jokingly suggests that the new feature should be implemented by giving 'static' another new meaning, completely unrelated to the existing three meanings. > ... If > they are related conceptually, I don't see it. Is there some relation > between these two things? ... None whatsoever. I've heard people argue otherwise, but their arguments didn't convince me. > 2. Ok, using extern in other modules to access the originally defined > variable. I understand this and how extern allows you to declare the > existence of a previously *defined* variable. However, I'm seeing > inconsistencies in the need to use extern for this purpose. I'm > referring to differences between 3 different compilers that are in 3 > different IDEs that I'm using: Visual Studio 2010, Code::Blocks and > Xcode (yes, I'm working on Objective-C too). In both of these examples > I've created a bare-bones C project with two modules. So, I've got > main.c and 2.c. I have a variable defined in main.c that's not inside > any function; let's call it int foo. In module 2.c, in theory I am > supposed to use 'extern int foo' in order to access that variable. > However, in Visual Studio and Code::Blocks I don't have to use 'extern'. > All I have to do is use the statement 'int foo' at the beginning of > the module, before any dependent functions and I can access the > originally defined int foo in main.c (the first module). The use of > extern is *not* necessary. ... What you've done there is create two separate external definitions for the same exact identifier, one in each translation unit. "If an identifier declared with external linkage is used in an expression (other than as part of the operand of a sizeof or _Alignof operator whose result is an integer constant), somewhere in the entire program there shall be exactly one external definition for the identifier; otherwise, there shall be no more than one." Code containing two external definitions for the same identifier violates a "shall" that occurs outside a constraints section. The behavior of such a program is undefined (4p6). "undefined behavior" only means that the C standard does not impose any requirements on the behavior. In particular, it does not require that your implementation give you any error messages. Because there are no requirements, Visual Studio is free to translate your program any way it wants. What it apparently wants to do is to merge the external definitions from your two different translation units, and treat them as the same object. This is actually a fairly popular choice. Personally, I'd prefer an error message. > ... I get the correct results. In Xcode it is > necessary, and not using extern causes linker errors...duplicate symbols > or something to that extent. That makes sense as technically I'm > incorrectly declaring int foo two times by not using extern for the > second time. So, why do Visual Studio and Code:Blocks allow me to do > this, I get the correct result, and there are no linker errors for both > of these IDEs? Since the C standard imposes no requirements on the behavior of such a program, the way that Code:Blocks deals with this code is just as acceptable as the way that Visual Studios does. -- James Kuyper
[toc] | [prev] | [next] | [standalone]
| From | Jon Rossen <jonr17@comcast.net> |
|---|---|
| Date | 2015-11-12 22:05 -0800 |
| Message-ID | <n23ukh$vb5$1@news.albasani.net> |
| In reply to | #75918 |
James, thanks for all this info; there is lots of stuff here to digest...Comments below inline -jonR On 11/12/2015 7:19 PM, James Kuyper wrote: > On 11/12/2015 09:47 PM, Jon Rossen wrote: > ... >> 1. Use of static to make a variable unusable by other modules: I get >> how this works with regards to the mechanics, buy not *why*. Let me >> explain: I understand what static does when used with a local variable; >> it allows the variable to retain it's value through multiple function >> calls. Let's say you have a function that does a page count or >> something such as that. Ok, I get all of this. But why then does the >> static keyword in front of a variable defined outside a function make >> that variable unusable by other modules? I don't see how this >> by-product of the keyword is related to the example I just illustrated >> with local variables. It seems like a programming non-sequitur. > > Don't worry about that - it just means that you're correctly perceiving > things. The static keyword has been given three entirely unrelated > meanings, depending upon the context: Ok, great. It's good to know that the reason I think it's screwed up is because I am starting to learn it accurately...particularly with respect to the fact that the different aspects of the feature aren't related to each other. > > 1. When applied to the definition of a file scope object or function, it > gives that object or function's identifier internal linkage. (6.2.2p3) > > 2. When applied to the definition of a block scope object, it gives that > object static storage duration.(6.2.4p3) > > 3. When used inside the leading dimension of a function parameter > declared as if it were an array, as in the following example: > > void func(int param[static 16]) > > it makes it undefined behavior to call func() with a pointer to that > does not give access to an array containing at least 16 items. > (6.7.6.3p7). This is a relatively new meaning, introduced in C99. I'm not sure I understand all of this yet. Btw, to give me a headstart or to cheat a bit, how do the two aspects of static that I mentioned (a) persistent values with local variables & b) disallowing the use of an external variable to be used in another module correlate to the 3 examples you gave above. As I said, I don't really fully understand this stuff yet. Btw, are those section/page sections you are pointing out at the end of your paragraphs? If so, to what publication? > > On comp.std.c, when someone suggests that a new feature be added to C, > there will often be someone who jokingly suggests that the new feature > should be implemented by giving 'static' another new meaning, completely > unrelated to the existing three meanings. Heh! That is hilarious. > >> ... If >> they are related conceptually, I don't see it. Is there some relation >> between these two things? ... > > None whatsoever. I've heard people argue otherwise, but their arguments > didn't convince me. Sounds like the guy who wrote his dissertation on the 3 Stooges. He claimed that they represented the id, ego and super ego. He was French and the title was 'Les Trois Imbecile'. He probably also liked Jerry Lewis, who is very popular in France. In any event maybe the people who argue that these 3 aspects of static are conceptually related are like the guy writing this crap about the 3 Stooges. > >> 2. Ok, using extern in other modules to access the originally defined >> variable. I understand this and how extern allows you to declare the >> existence of a previously *defined* variable. However, I'm seeing >> inconsistencies in the need to use extern for this purpose. I'm >> referring to differences between 3 different compilers that are in 3 >> different IDEs that I'm using: Visual Studio 2010, Code::Blocks and >> Xcode (yes, I'm working on Objective-C too). In both of these examples >> I've created a bare-bones C project with two modules. So, I've got >> main.c and 2.c. I have a variable defined in main.c that's not inside >> any function; let's call it int foo. In module 2.c, in theory I am >> supposed to use 'extern int foo' in order to access that variable. >> However, in Visual Studio and Code::Blocks I don't have to use 'extern'. >> All I have to do is use the statement 'int foo' at the beginning of >> the module, before any dependent functions and I can access the >> originally defined int foo in main.c (the first module). The use of >> extern is *not* necessary. ... > > What you've done there is create two separate external definitions for > the same exact identifier, one in each translation unit. > > "If an identifier declared with external linkage is used in an > expression (other than as part of the operand of a sizeof or > _Alignof operator whose result is an integer constant), somewhere in the > entire program there shall be exactly one external definition for the > identifier; otherwise, there shall be no more than one." > > Code containing two external definitions for the same identifier > violates a "shall" that occurs outside a constraints section. The > behavior of such a program is undefined (4p6). "undefined behavior" only > means that the C standard does not impose any requirements on the > behavior. In particular, it does not require that your implementation > give you any error messages. Because there are no requirements, Visual > Studio is free to translate your program any way it wants. What it > apparently wants to do is to merge the external definitions from your > two different translation units, and treat them as the same object. This > is actually a fairly popular choice. Personally, I'd prefer an error > message. Ok, thanks for the explanation; I find it interesting. It does seem contradictory, unless I'm not fully understanding the discussion you are presenting. It's called 'undefined behavior' which means that the C standard doesn't impose any requirements on the behavior. Why then does the language then have 'extern' which seems to want to make this orderly? You would think since 'extern' exists, there would be requirements for this. > >> ... I get the correct results. In Xcode it is >> necessary, and not using extern causes linker errors...duplicate symbols >> or something to that extent. That makes sense as technically I'm >> incorrectly declaring int foo two times by not using extern for the >> second time. So, why do Visual Studio and Code:Blocks allow me to do >> this, I get the correct result, and there are no linker errors for both >> of these IDEs? > > Since the C standard imposes no requirements on the behavior of such a > program, the way that Code:Blocks deals with this code is just as > acceptable as the way that Visual Studios does. > Ok, just to make sure we're on the same page, I did state that Visual Studio and Code::Blocks both work the same way with respect to this..well maybe completely under the hood but the end results are the same. So, you are saying that VS and C::B are both acceptable. I guess since you stated you would prefer an error message, you would favor the behavior of Xcode which put up a linker error message. thanks
[toc] | [prev] | [next] | [standalone]
| From | Richard Heathfield <rjh@cpax.org.uk> |
|---|---|
| Date | 2015-11-13 07:10 +0000 |
| Message-ID | <n24299$ngj$1@dont-email.me> |
| In reply to | #75924 |
On 13/11/15 06:05, Jon Rossen wrote: > James, thanks for all this info; there is lots of stuff here to > digest...Comments below inline -jonR > > On 11/12/2015 7:19 PM, James Kuyper wrote: >> On 11/12/2015 09:47 PM, Jon Rossen wrote: <snip> >>> I've created a bare-bones C project with two modules. So, I've got >>> main.c and 2.c. I have a variable defined in main.c that's not inside >>> any function; let's call it int foo. In module 2.c, in theory I am >>> supposed to use 'extern int foo' in order to access that variable. >>> However, in Visual Studio and Code::Blocks I don't have to use 'extern'. >>> All I have to do is use the statement 'int foo' at the beginning of >>> the module, before any dependent functions and I can access the >>> originally defined int foo in main.c (the first module). The use of >>> extern is *not* necessary. ... >> >> What you've done there is create two separate external definitions for >> the same exact identifier, one in each translation unit. [James is of course quite right here, so this isn't a matter of debate but a matter of exegesis.] >> [...] the C standard does not impose any requirements on the >> behavior. In particular, it does not require that your implementation >> give you any error messages. Because there are no requirements, Visual >> Studio is free to translate your program any way it wants. What it >> apparently wants to do is to merge the external definitions from your >> two different translation units, and treat them as the same object. This >> is actually a fairly popular choice. Personally, I'd prefer an error >> message. > > Ok, thanks for the explanation; I find it interesting. It does seem > contradictory, unless I'm not fully understanding the discussion you are > presenting. It's called 'undefined behavior' which means that the C > standard doesn't impose any requirements on the behavior. Why then does > the language then have 'extern' which seems to want to make this > orderly? You would think since 'extern' exists, there would be > requirements for this. There are such requirements, but it is not possible to enforce them because it's impossible for the compiler to distinguish between this: int x; /* This is defined at file scope, and taking default value of 0 */ and this: int x; /* I wrongly believed adding this would allow me to access the int x defined at file scope in another module. */ It is only at the linking stage that the system could conceivably spot something amiss, and a good linker is likely to complain (via a diagnostic message) that there are two symbols whose names clash, but C does not insist on such a message as far as I'm aware. (Caveat: I didn't look it up, because I'm still on my first coffee of the day.) >>> ... I get the correct results. In Xcode it is >>> necessary, and not using extern causes linker errors...duplicate symbols >>> or something to that extent. That makes sense as technically I'm >>> incorrectly declaring int foo two times by not using extern for the >>> second time. So, why do Visual Studio and Code:Blocks allow me to do >>> this, I get the correct result, and there are no linker errors for both >>> of these IDEs? >> >> Since the C standard imposes no requirements on the behavior of such a >> program, the way that Code:Blocks deals with this code is just as >> acceptable as the way that Visual Studios does. >> > > Ok, just to make sure we're on the same page, I did state that Visual > Studio and Code::Blocks both work the same way with respect to > this. And that's fine. When a program exhibits undefined behaviour, implementations have licence from the C Standard to behave any way they damn well please (subject to applicable legislation, but not necessarily in obedience to physical law - if your program exhibits undefined behaviour, the implementation is perfectly entitled to send all your computers (not just the one you're running the program on) back to the Pre-Cambrian Era and set up a breeding program to replace the entire human race with something a little more rational. So please have a care). <snip> -- Richard Heathfield Email: rjh at cpax dot org dot uk "Usenet is a strange place" - dmr 29 July 1999 Sig line 4 vacant - apply within
[toc] | [prev] | [next] | [standalone]
| From | James Kuyper <jameskuyper@verizon.net> |
|---|---|
| Date | 2015-11-13 08:33 -0500 |
| Message-ID | <n24om3$5sb$1@dont-email.me> |
| In reply to | #75924 |
On 11/13/2015 01:05 AM, Jon Rossen wrote: > James, thanks for all this info; there is lots of stuff here to > digest...Comments below inline -jonR > > On 11/12/2015 7:19 PM, James Kuyper wrote: ... >> things. The static keyword has been given three entirely unrelated >> meanings, depending upon the context: > > Ok, great. It's good to know that the reason I think it's screwed up is > because I am starting to learn it accurately...particularly with respect > to the fact that the different aspects of the feature aren't related to > each other. > >> >> 1. When applied to the definition of a file scope object or function, it >> gives that object or function's identifier internal linkage. (6.2.2p3) >> >> 2. When applied to the definition of a block scope object, it gives that >> object static storage duration.(6.2.4p3) >> >> 3. When used inside the leading dimension of a function parameter >> declared as if it were an array, as in the following example: >> >> void func(int param[static 16]) >> >> it makes it undefined behavior to call func() with a pointer to that >> does not give access to an array containing at least 16 items. >> (6.7.6.3p7). This is a relatively new meaning, introduced in C99. > > I'm not sure I understand all of this yet. Btw, to give me a headstart > or to cheat a bit, how do the two aspects of static that I mentioned (a) > persistent values with local variables That's "static storage duration". What that means is that the variable storage exists from the start of the program to the very end of the program, so what you stored in it at one time is still there the next time you look at it. All file scope objects have static storage duration; other objects have static storage duration only if declared 'static'. The most common alternative is "automatic storage duration", which applies to function parameters and all objects defined inside of functions, unless declared 'static'. These object have storage with a lifetime that starts when control enters the block where they are defined, and ends when the block is exited (for function parameters, the relevant block is the outermost block of the function). Each time the lifetime of an object starts, it's a new object, which might be located at a different address than the previous time. If an initializer is provided, it gets initialized to the specified value each time (unless control jumps into the block at some point after the initialization using switch, goto or longjmp()) - otherwise, the object's value is uninitialized. Either way, any value stored in it during a previous lifetime was lost when that lifetime ended. There's also thread storage duration, which is new in C2011, which applies to objects declared _Thread_local - their lifetime begins and ends with the creation and destruction of the corresponding thread. The other option is dynamic storage duration, which applies to dynamically allocated objects, which are created by a call to malloc(), calloc() or realloc(), and can be destroyed by a call to free() or realloc(). & b) disallowing the use of an > external variable to be used in another module correlate to the 3 > examples you gave above. That's internal linkage. Being available from other modules is external linkage. > ... As I said, I don't really fully understand > this stuff yet. Btw, are those section/page sections you are pointing > out at the end of your paragraphs? If so, to what publication? The current C standard, C2011. If you google for n1570.pdf, you can get a free copy that is almost identical to the finally approved standard. If you'd like to pay huge sums of money, you can get a copy of the final standard from ISO, or from your country's own standards organization, assuming that it's a member of ISO. ... >>> 2. Ok, using extern in other modules to access the originally defined >>> variable. I understand this and how extern allows you to declare the >>> existence of a previously *defined* variable. However, I'm seeing >>> inconsistencies in the need to use extern for this purpose. I'm >>> referring to differences between 3 different compilers that are in 3 >>> different IDEs that I'm using: Visual Studio 2010, Code::Blocks and >>> Xcode (yes, I'm working on Objective-C too). In both of these examples >>> I've created a bare-bones C project with two modules. So, I've got >>> main.c and 2.c. I have a variable defined in main.c that's not inside >>> any function; let's call it int foo. In module 2.c, in theory I am >>> supposed to use 'extern int foo' in order to access that variable. >>> However, in Visual Studio and Code::Blocks I don't have to use 'extern'. >>> All I have to do is use the statement 'int foo' at the beginning of >>> the module, before any dependent functions and I can access the >>> originally defined int foo in main.c (the first module). The use of >>> extern is *not* necessary. ... >> >> What you've done there is create two separate external definitions for >> the same exact identifier, one in each translation unit. >> >> "If an identifier declared with external linkage is used in an >> expression (other than as part of the operand of a sizeof or >> _Alignof operator whose result is an integer constant), somewhere in the >> entire program there shall be exactly one external definition for the >> identifier; otherwise, there shall be no more than one." >> >> Code containing two external definitions for the same identifier >> violates a "shall" that occurs outside a constraints section. The >> behavior of such a program is undefined (4p6). "undefined behavior" only >> means that the C standard does not impose any requirements on the >> behavior. In particular, it does not require that your implementation >> give you any error messages. Because there are no requirements, Visual >> Studio is free to translate your program any way it wants. What it >> apparently wants to do is to merge the external definitions from your >> two different translation units, and treat them as the same object. This >> is actually a fairly popular choice. Personally, I'd prefer an error >> message. > > Ok, thanks for the explanation; I find it interesting. It does seem > contradictory, unless I'm not fully understanding the discussion you are > presenting. It's called 'undefined behavior' which means that the C > standard doesn't impose any requirements on the behavior. Why then does > the language then have 'extern' which seems to want to make this > orderly? You would think since 'extern' exists, there would be > requirements for this. The purpose of 'extern' is to give such code defined behavior. Declarations containing 'extern' are NOT definitions. Therefore, if you put 'extern' on all but one of the declarations, everything is fine. C requires you to identify which one is the actual definition; the others are just references to the actual definition. It would certainly be feasible to require that all such definitions be merged, but the committee decided not to impose such a requirement - at the time when that decision was made, it would have been excessively burdensome on some platforms. >>> ... I get the correct results. In Xcode it is >>> necessary, and not using extern causes linker errors...duplicate symbols >>> or something to that extent. That makes sense as technically I'm >>> incorrectly declaring int foo two times by not using extern for the >>> second time. So, why do Visual Studio and Code:Blocks allow me to do >>> this, I get the correct result, and there are no linker errors for both >>> of these IDEs? >> >> Since the C standard imposes no requirements on the behavior of such a >> program, the way that Code:Blocks deals with this code is just as >> acceptable as the way that Visual Studios does. >> > > Ok, just to make sure we're on the same page, I did state that Visual > Studio and Code::Blocks both work the same way with respect to > this..well maybe completely under the hood but the end results are the > same. So, you are saying that VS and C::B are both acceptable. I guess > since you stated you would prefer an error message, you would favor the > behavior of Xcode which put up a linker error message. That was a mistake on my part. If I'd read your paragraph a little more carefully, I would have mentioned all three compilers. -- James Kuyper
[toc] | [prev] | [next] | [standalone]
| From | Tim Rentsch <txr@alumni.caltech.edu> |
|---|---|
| Date | 2015-11-13 12:24 -0800 |
| Message-ID | <kfn6115r6k5.fsf@x-alumni2.alumni.caltech.edu> |
| In reply to | #75946 |
ram@zedat.fu-berlin.de (Stefan Ram) writes: > [...] write a >>tentative definition<<, which can be both a > definition or a pure declaration, depending on other parts > of the code. A tentative definition is always a tentative definition, regardless of whether there is an external definition (ie, with an initializer) either before or after or neither. A tentative definition is never a definition. The presence of a tentative definition in a translation unit results in the identifier declared being given a definition (with an initializer equal to 0) if the translation unit doesn't define the identifier otherwise, but that doesn't turn the tentative definition into a definition.
[toc] | [prev] | [next] | [standalone]
| From | Keith Thompson <kst-u@mib.org> |
|---|---|
| Date | 2015-11-14 11:58 -0800 |
| Message-ID | <lnpozcnyk2.fsf@kst-u.example.com> |
| In reply to | #75946 |
James Kuyper <jameskuyper@verizon.net> writes:
> The other option is dynamic storage duration, which applies to
> dynamically allocated objects, which are created by a call to
> malloc(), calloc() or realloc(), and can be destroyed by a call to
> free() or realloc().
The standard calls that "allocated" storage duration.
--
Keith Thompson (The_Other_Keith) kst-u@mib.org <http://www.ghoti.net/~kst>
Working, but not speaking, for JetHead Development, Inc.
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
[toc] | [prev] | [next] | [standalone]
| From | James Kuyper <jameskuyper@verizon.net> |
|---|---|
| Date | 2015-11-14 15:27 -0500 |
| Message-ID | <56479914.8040305@verizon.net> |
| In reply to | #76009 |
On 11/14/2015 02:58 PM, Keith Thompson wrote: > James Kuyper <jameskuyper@verizon.net> writes: >> The other option is dynamic storage duration, which applies to >> dynamically allocated objects, which are created by a call to >> malloc(), calloc() or realloc(), and can be destroyed by a call to >> free() or realloc(). > > The standard calls that "allocated" storage duration. Sorry - I mixed up the C and C++ terms. It didn't sound quite right to me, and I would have checked before posting, but I had to rush because I was almost late for a doctor's appointment (actually, I thought I was late - but two of my mistakes canceled each other out, so I made it in time).
[toc] | [prev] | [next] | [standalone]
| From | Malcolm McLean <malcolm.mclean5@btinternet.com> |
|---|---|
| Date | 2015-11-12 14:00 -0800 |
| Message-ID | <ff93eba5-77c4-48f9-84dc-2181f202f64b@googlegroups.com> |
| In reply to | #75880 |
On Thursday, November 12, 2015 at 9:33:15 PM UTC, Jon Rossen wrote:
> Hi all, I'm fairly new to programming and have a question on the C
> language with regards to variable scope, compilers and the 'extern'
> keyword. I'm using a couple of books that seem to have info that is not
> in keeping with my results. Here's a simple little trivial code example
> that illustrates the question:
>
> #include <stdio.h>
>
> int x = 999;
> void print_value(void);
>
> int main(void)
> {
> extern int x; // This entire statement is not necessary to
> // get the proper results, why??
>
> printf("%d\n", x);
> print_value();
>
> return 0;
> }
>
> void print_value(void)
> {
> extern int x; // This obviously is
> printf("%d\n", x);
> }
>
Essentially you've got three scopes in C; function scope, file scope,
and global scope.
A function scope variable is declared in the block at the top
of the function it is local to. I comes into existence when the
function is called, is destroyed when it returns, and is not
available to subroutines, although it can be passed in (and this
is in fact very common).
A file scope variable exists for the entire duration of the program.
However it is only available to functions with in the that source
file. You declare it lie this
/* foo.c */
static int x = 0; /* Note the static */
int foo(void)
{
return x++;
}
int bar(void)
{
return x--;
}
x is acting as a sort of counter for calls to foo() and bar().
A global you declare like this
/* foo .c */
int foo_x = 42; /* no static. Don't call it just "x", that would */
/* be asking for a name collision */
/* foo.h */
extern int foo_x; /* Note the extern. This tells everyone who */
/* include foo.h about foo_x */
/* bar.c */
#include "foo.h" /* get the link to the variable */
int bar(void)
{
return foo_x--; /* we've got rad and writer access to foo_x */
}
[toc] | [prev] | [next] | [standalone]
| From | Richard Heathfield <rjh@cpax.org.uk> |
|---|---|
| Date | 2015-11-12 23:55 +0000 |
| Message-ID | <n238p5$os0$1@dont-email.me> |
| In reply to | #75884 |
On 12/11/15 22:00, Malcolm McLean wrote:
<snip>
>>
> Essentially you've got three scopes in C; function scope, file scope,
> and global scope.
There are actually four kinds of scope, and those three are two of them.
The scopes are:
* function prototype scope (and we can quietly ignore that for now);
* function scope;
* file scope;
* block scope.
There is no such thing as "global scope".
> A function scope variable is declared in the block at the top
> of the function it is local to. I comes into existence when the
> function is called, is destroyed when it returns, and is not
> available to subroutines, although it can be passed in (and this
> is in fact very common).
No, there is no such thing as a function scope variable. The only
identifiers that can have function scope are labels.
> A file scope variable exists for the entire duration of the program.
Scope is a property of identifiers, and may be thought of as the part of
a source file in which an identifier is *visible*. You are confusing
scope with lifetime.
> However it is only available to functions with in the that source
> file. You declare it lie this
>
> /* foo.c */
>
> static int x = 0; /* Note the static */
Note that the absence of static does not stop this being a file scope
identifier.
<snip>
> A global you declare like this
It's tricky to be precise about terms like "global", but we can be very
precise about the difference between, say, file scope and block scope.
>
> /* foo .c */
>
> int foo_x = 42; /* no static. Don't call it just "x", that would */
> /* be asking for a name collision */
That's a file scope identifier with external linkage. It is not a
"global scope" identifier because there is no such thing as "global
scope" in C.
For completeness (ish), block scope identifiers are defined like this:
while(y--)
{
int bsi = 0;
while(dosomethingwith(bsi, y) > 0)
{
++bsi;
}
}
Block scopes can be created very easily:
stuff();
nonsense();
{ /* block scope starts */
int absi = 0; /* absi is visible from here to the end of the block */
while(dosomethingwith(absi, y) > 0)
{
++absi;
}
} /* block scope ends, absi no longer visible */
more_nonsense();
more_stuff();
(That is, for/while/do-while/switch/if aren't the only places you can
have a block scope.)
--
Richard Heathfield
Email: rjh at cpax dot org dot uk
"Usenet is a strange place" - dmr 29 July 1999
Sig line 4 vacant - apply within
[toc] | [prev] | [next] | [standalone]
| From | Keith Thompson <kst-u@mib.org> |
|---|---|
| Date | 2015-11-12 17:11 -0800 |
| Message-ID | <lnio56pusk.fsf@kst-u.example.com> |
| In reply to | #75880 |
Jon Rossen <jonr17@comcast.net> writes:
> Hi all, I'm fairly new to programming and have a question on the C
> language with regards to variable scope, compilers and the 'extern'
> keyword. I'm using a couple of books that seem to have info that is not
> in keeping with my results. Here's a simple little trivial code example
> that illustrates the question:
>
> #include <stdio.h>
>
> int x = 999;
> void print_value(void);
>
> int main(void)
> {
> extern int x; // This entire statement is not necessary to
> // get the proper results, why??
>
> printf("%d\n", x);
> print_value();
>
> return 0;
> }
>
> void print_value(void)
> {
> extern int x; // This obviously is
> printf("%d\n", x);
> }
>
> Result: 999
> 999
The "extern int x;" declaration (not statement) is not necessary either
in main or in print_value. The file-scope definition of x is visible in
both functions.
--
Keith Thompson (The_Other_Keith) kst-u@mib.org <http://www.ghoti.net/~kst>
Working, but not speaking, for JetHead Development, Inc.
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
[toc] | [prev] | [next] | [standalone]
| From | Jon Rossen <jonr17@comcast.net> |
|---|---|
| Date | 2015-11-12 20:39 -0800 |
| Message-ID | <n23pj3$mrg$2@news.albasani.net> |
| In reply to | #75906 |
On 11/12/2015 5:11 PM, Keith Thompson wrote:
> Jon Rossen <jonr17@comcast.net> writes:
>> Hi all, I'm fairly new to programming and have a question on the C
>> language with regards to variable scope, compilers and the 'extern'
>> keyword. I'm using a couple of books that seem to have info that is not
>> in keeping with my results. Here's a simple little trivial code example
>> that illustrates the question:
>>
>> #include <stdio.h>
>>
>> int x = 999;
>> void print_value(void);
>>
>> int main(void)
>> {
>> extern int x; // This entire statement is not necessary to
>> // get the proper results, why??
>>
>> printf("%d\n", x);
>> print_value();
>>
>> return 0;
>> }
>>
>> void print_value(void)
>> {
>> extern int x; // This obviously is
>> printf("%d\n", x);
>> }
>>
>> Result: 999
>> 999
>
> The "extern int x;" declaration (not statement) is not necessary either
> in main or in print_value. The file-scope definition of x is visible in
> both functions.
>
Thanks, Keith. Yeah, this has already been cleared up earlier. I had
some other questions but this central one was the result of an obvious
mistake on my part. I think I had my head stuck somewhere; let's just
call it cranial/rectal inversion.
[toc] | [prev] | [next] | [standalone]
| From | Jon Rossen <jonr17@comcast.net> |
|---|---|
| Date | 2015-11-12 20:38 -0800 |
| Message-ID | <n23pg8$mrg$1@news.albasani.net> |
| In reply to | #75880 |
On 11/12/2015 4:25 PM, Stefan Ram wrote: > Jon Rossen <jonr17@comcast.net> writes: >> extern int x; // This entire statement is not necessary to > > It's not a statement, it's a declaration (a block-item). > >> omit the 'extern int x' statement completely, > > »extern int ׫ is not a statement. > Couldn't it be considered both? In other words can't the term 'statement' be considered a superset that includes smaller subsets such as declarations?
[toc] | [prev] | [next] | [standalone]
Page 1 of 2 [1] 2 Next page →
Back to top | Article view | comp.lang.c
csiph-web