Can C++ Have Code in the Global Scope

Can C++ have code in the global scope?

The answer on the question you linked to was talking in a simple way, not using strict C++ naming for constructs.

Being more pedantic, C++ does not have "code". C++ has declarations, definitions, and statements. Statements are what you probably think of as "code": if, for, expressions, etc.

Only declarations and definitions can appear at global scope. Of course, definitions can include expressions. int a = 5; defines a global variable, initialized by an expression.

But you can't just have a random statement/expression at global scope, like a = 5;. That is, expressions can be part of definitions, but an expression is not a definition.

You can call functions before main of course. Global variable constructors and initializers which are too complex to be executed at compile time have to run before main. For example:

int b = []()
{
std::cout << "Enter a number.\n";
int temp;
std::cin >> temp;
return temp;
}();

The compiler can't do that at compile-time; it's interactive. And C++ requires that all global variables are initialized before main begins. So the compiler will have to invoke code pre-main. Which is perfectly legal.

Every C++ compilation and execution system has some mechanism for invoking code before and after main. Globals have to be initialized, and object constructors may need to be called to do that initialization. After main completes, global variables have to be destroyed, which means destructors need to be called.

Why can't I assign values to global variables outside a function in C?

This is a definition of a global variable, with the optional initialisation to a specific value:

int i = 8;

Note that it is not code which gets ever executed, the variable will just be set up to initially contain the 8. Either consider it "magic" (a helpful model for many things not really defined by the standard) or think of tables with values being copied to memory locations before any code is executed.

This is a piece of code which has no "frame" in which it is executed.

(Or you intend it to be. The compiler is of other opinion, see below.)

i = 9;

There is no function containing it. It is not clear when it should be executed. That is what the compiler does not like.

In C, all code has to be inside a function and will only be executed if that function is called, e.g. from main().

Other language, mostly those which execute "scripts" by interpreting them (instead of code being turned into executeables, e.g. by a compiler) allow to have code anywhere. C is different.

The compiler sees this differently:

i = 9;
  • it is not inside a function, so it cannot be code
  • it looks like a variable definition, assuming that you mean it to be an int, i.e. the default
  • but relying on defaults is not a good idea, so warn about missing type and that the default is used
  • also, if it is a definition, then it is the second one for i, now that is really wrong, so show an error and fail the compiling
  • just to be helpful, mention where the first definition of i is

That is how to read the compiler output you have quoted.

How to access local and global variable with same name in C

You could cheat and create a pointer to the global i before declaring the local i:

void fun2( void )
{
int *ip = &i; // get address of global i
int i = 50; // local i ”shadows" global i

printf( "local i = %d, global i = %d\n", i, *ip );
}

EDIT

Seeing as this answer got accepted, I must emphasize that you should never write code like this. This is a band-aid around poor programming practice.

Avoid globals where possible, and where not possible use a naming convention that clearly marks them as global and is unlikely to be shadowed (such as prefixing with a g_ or something similar).

I can't tell you how many hours I've wasted chasing down issues that were due to a naming collision like this.

When is it ok to use a global variable in C?

Variables should always have a smaller scope possible. The argument behind that is that every time you increase the scope, you have more code that potentially modifies the variable, thus more complexity is induced in the solution.

It is thus clear that avoiding using global variables is preferred if the design and implementation naturally allow that. Due to this, I prefer not to use global variables unless they are really needed.

I can not agree with the 'never' statement either. Like any other concept, global variables are something that should be used only when needed. I would rather use global variables than using some artificial constructs (like passing pointers around), which would only mask the real intent.

Some good examples where global variables are used are singleton pattern implementations or register access in embedded systems.

On how to actually detect excessive usages of global variables: inspection, inspection, inspection. Whenever I see a global variable I have to ask myself: Is that REALLY needed at a global scope?

In C, how do I restrict the scope of a global variable to the file in which it's declared?

You #included bar.c, which has the effect of causing the preprocessor to literally copy the contents of bar.c into foo.c before the compiler touches it.

Try getting rid of the include, but telling your compiler to compile both files (e.g. gcc foo.c bar.c) and watch it complain as you expect.

Edit: I suppose the primary confusion is between the compiler and the preprocessor. Language rules are enforced by the compiler. The preprocessor runs before the compiler, and acts on those commands prefixed by #. All the preprocessor does is manipulate plain text. It doesn't parse the code or try to interpret the meaning of the code in any way. The "#include" directive is very literal - it tells the preprocessor "insert the contents of this file here". This is why you normally only use #include on .h (header) files, and you only place function prototypes and extern variable declarations in header files. Otherwise, you will end up compiling the same functions, or defining the same variables, multiple times, which is not legal.

Functions declared within a function in C, are they usable at a global scope?

Declarations are needed for type checking and linking. They exist at compile-time only - they don't actually create an "object" (such as a function body) that exists in any way in the compiled program - all they do is put a name on it, so that other parts of the source can refer to that object without having it immediately to hand. Definitions create objects, but declarations create names.

Going through your example:

void roo(void);  // roo becomes visible

int main(){ // main is defined, AND becomes visible
void foo(int bar); // foo becomes visible
foo(6);
roo();
} // foo is no longer visible

void foo(int bar){ /**/ } // foo is defined AND becomes visible

void roo(void){ // roo is defined, but was already visible
foo(6); // so this has no effect on other functions
}
  1. roo can be called from any code in the program below where it was declared, because its name has been put in global scope and is visible from all nested scopes. The following code is aware that somewhere (no idea where), a function called roo exists and is available for use.

  2. Moving down into main, a new scope is opened, and foo made visible within it. main uses this information to call to foo. It uses the information in the global scope to call to roo. The scope closes with the end of main and foo ceases to be visible to the following code; it is not aware that any such function exists.

  3. foo is the simultaneously defined and declared in the global scope. All following code is aware that a function called foo is available for use.

  4. Similarly for roo.

The only places anything is given space in memory are at the three points of definition. None of the declarations cause anything to be allocated, statically or otherwise. All they do is make the code aware of an allocation elsewhere (to be resolved by the linker).


So to (what I think was) the original point of confusion: main calls roo, and roo calls foo, but the declaration of foo in main is not visible to roo. (It sounds like you're confusing static and dynamic semantics: C has static scope only.)

This isn't a problem, because main doesn't know the content of roo, and doesn't need to know its content (some compilers perform inlining; we don't care about that). Control leaves the body code of main and goes to a different point in the program. The body of a function is a black box to every other function; what happens within the code of roo is completely unknown to every other function. roo also doesn't inherit the scope of main, so it has no knowledge of anything that was declared at that time (globally, locally, or otherwise) - it uses the scope opened and closed by its own body further down for name lookups. In that scope, foo has already been declared globally (it inherits the global scope at a separate fixed point on the page), so roo can see foo of its own accord.

Each function exists in one (and exactly one) place. All declarations do is make that place visible to the code that uses it. Code that doesn't use it, doesn't need to be able to see it. main can't see the nested call to foo, so any declaration at that point isn't relevant to it.



Related Topics



Leave a reply



Submit