2

Following is a very simple c++ code:-

#include <iostream>
using namespace std;

int i;
i = 2;     //error at line 5
int main()
{
    cout << i << endl;
    return 0;
}

Total 3 errors are produced due to line 5:-

  • this declaration has no storage class or type specifier

  • missing type specifier - int assumed. Note: C++ does not support default-int

  • 'int i': redefinition

I knew that line 5 is syntactically wrong but I couldn't find any reason for it.

I have just started learning C++ from the book C++: A Complete Reference by Herbert Schildt. In chapter 2 while understanding extern keyword, it was wriiten that

A declaration declares the name and type of an object. A definition causes storage to be allocated for the object.

From this, I deduced that statements of the form {type}{variable_name} are declarations while first assignment statements i.e., {variable_name} ={first_value} can be thought of as definition.

But for global variables, declarations are definitions because if they aren't initialized, they are given a default value. So in the given code, at line 4, i should be initialized with default value 0 and then, at line 5, i is just given another value, 2 but outside main().

Usually, global variables are initialized inside main and they cannot be assigned values like this outside main. If the same is done with any other type of variable like with local variables, no error is raised.

Similar question was asked in this thread.

I couldn't understand the answer given by paxdiablo completely. It says before main() is being compiled, there is no b and gave 2 solutions. Either initailize variable b while declaring it before main() gets invoked or use extern to tell the compiler that the variable, b is used somewhere else.

I used the former solution in a slightly different way. First, I declared the global variable, i and then I assigned it a value before main() gets invoked.

So, why globals (whether static or not) can't be defined or assigned to a value in a separate line of code outside main() even if the assignment is done before main()?


Note: I have just started studying C++. So it may be possible that my deductions are wrong. Before C++, I did python, so it's becoming a bit difficult for me to understand the initialisation and compilation order of the C++ code. So, sorry if it becomes a little too inconvenient for you all.
Perspicacious
  • 594
  • 3
  • 17
  • In your code, `int i;` declares a static variable. Globals are static by default. Not static in the OOP sense, but static linkage. – Guillaume Racicot Jul 02 '19 at 16:08
  • 3
    Don't use global variables. Just *don't*. Although they are legal and have well defined behaviour, they lead to tight coupling of different parts of your code, are hard to reason about (since *anyone* may have modified them), lead to problems when dynamically loading shared objects, are hard for the compiler to optimize, and much much more. *Don't* use global variables (or singletons, which are just global variables in fancy dresses). – Jesper Juhl Jul 02 '19 at 16:09
  • @JesperJuhl I use global variables all the time. However they mostly are constexpr or const. Also, I see nothing wrong using global state for some things. Sure global are *abused* by programmers but it's not a reason to ban them. – Guillaume Racicot Jul 02 '19 at 16:10
  • 1
    @GuillaumeRacicot You can, of course, do whatever you want. But in *my* opinion you are doing something misguided and something that will eventually bite you. Although if they are constants, the pain is of course less. But I don't think I want to work in your code base. But, that's just me. Do whatever you want. This is all opinion. I've just been bitten one time more than is funny, so in my world they are banned. – Jesper Juhl Jul 02 '19 at 16:13
  • 1
    @GuillaumeRacicot Global variables make refactoring unnecessarily hard in bigger codebases. I am fully backing up what Jesper says. – πάντα ῥεῖ Jul 02 '19 at 16:18
  • @πάνταῥεῖ Shared mutable states are making programs hard to think about. Globals amplify the problem. Most of my globals are in type traits, but you have to use globals for that. That or string-to-enum tables. But it's not share mutable state. – Guillaume Racicot Jul 02 '19 at 16:32
  • While Schildt is well known for not being one of the better authors on C++, there is no way you can deduce that from the quoted sentences. – molbdnilo Jul 02 '19 at 16:36
  • @JesperJuhl My codebase is using a few enum to string tables and lots of type traits. I wonder if you ever had trouble with `std::is_enum<>::value`, since it's a global. Also, most constexpr are better off global. As I said to πάντα ῥεῖ, shared mutable state makes program hard to think about. Globals are only an amplification of that. – Guillaume Racicot Jul 02 '19 at 16:36
  • @GuillaumeRacicot Of course there are exceptions to *any* rule. *Some* globals are OK, especially if they don't maintain state (like `std::cout`). You can *always* find an example where some bad thing is good. I'm just saying that *in general*, globals are bad and should be avoided. – Jesper Juhl Jul 02 '19 at 16:42
  • Thanks for such valuable inputs. @GuillaumeRacicot, you said that globals have static linkage by default so `i` can be visible in that file only in which it is declared. But I just used it in another file using *extern* keyword. – Perspicacious Jul 03 '19 at 11:57

0 Answers0