MESSAGE
DATE | 2010-02-13 |
FROM | Ruben Safir
|
SUBJECT | Subject: [NYLXS - HANGOUT] C++ Workshop - side discussing on C++ variable declarations
|
There is another caveat I'm running into here. The folding local scope inside functions has to be something you need to be aware of. If your using an extern variable in from a header file, and try to define it inside of a function, your created a local variable to that function and it is not going to act like a global variable.
Ruben
On Sat, Feb 13, 2010 at 08:43:04PM -0500, Ruben Safir wrote: > Alright - I'm top posting :) > > Here is an example of the error that I had in mind, and you'll see how > the linker behaves, although I thought I might get a different behavior. > > http://www.nylxs.com/docs/workshops/scope/ > > > First > > The header file construction: scope.h > > --- > > #ifndef SCOPETEST > #define SCOPETEST > #endif > > using namespace std; > > extern int global_i; > int global_def; > void test_obj(); > void test_obj2(); > ------ > > First Library File Construction: scope1.cc > > ----- > #include "scope.h" > #include > > void test_obj(){ > int global_i = 5; > global_def = 200; > cout << "Global Declared Variable ==>" << global_i << endl; > cout << "Global defined Variable ==>" << global_def << endl; > } > > > > _______ > > > Second Library Source File Construction: scope2.cc > > ______ > > #include "scope.h" > #include > > void test_obj2(){ > int global_i = 5; > global_def = 300; > cout << "Global Declared Variable ==>" << global_i << endl; > cout << "Global defined Variable ==>" << global_def << endl; > } > > > > ________ > > The main programming file: scope_main.cc > > ----------- > #include > #include "scope.h" > > using namespace std; > > int main(int argv, char * argc[]){ > int global_i = 25; > // int global_def; > cout << "Global Declare " << global_i << endl; > cout << "Global Declare " << global_def << endl; > > test_obj(); > test_obj2(); > return 0; > } > > ____________ > > > Not create a makefile that produces two seperate object files, one for > each libary source file: makefile > > _____________ > > scope : scope1.o scope2.o scope_main.o > g++ -o scope scope_main.o scope1.o scope2.o > > scope1.o : scope1.cc scope.h > g++ -Wall -c scope1.cc > > scope2.o : scope2.cc scope.h > g++ -Wall -c scope2.cc > > file5_main.o : scope_main.cc > g++ -Wall -c scope_main.cc > _____________ > > > Now compile > > ruben-at-www2:/usr/local/apache/htdocs/nylxs/docs/workshops/scope> make > g++ -Wall -c scope1.cc > g++ -Wall -c scope2.cc > g++ -c -o scope_main.o scope_main.cc > g++ -o scope scope_main.o scope1.o scope2.o > scope1.o:(.bss+0x0): multiple definition of `global_def' > scope_main.o:(.bss+0x0): first defined here > scope2.o:(.bss+0x0): multiple definition of `global_def' > scope_main.o:(.bss+0x0): first defined here > collect2: ld returned 1 exit status > make: *** [scope] Error 1 > > > Lets look at that output individually > > The compiler creates all the objects (3 of them in this case) without a > problem: > > g++ -Wall -c scope1.cc > g++ -Wall -c scope2.cc > g++ -c -o scope_main.o scope_main.cc > > > ruben-at-www2:/usr/local/apache/htdocs/nylxs/docs/workshops/scope> ls -al *o > -rw-r--r-- 1 ruben users 2272 2010-02-13 19:52 scope1.o > -rw-r--r-- 1 ruben users 2272 2010-02-13 19:52 scope2.o > -rw-r--r-- 1 ruben users 2312 2010-02-13 19:52 scope_main.o > > ruben-at-www2:/usr/local/apache/htdocs/nylxs/docs/workshops/scope> nm scope1.o > 000000c7 t _GLOBAL__I_global_def > 00000087 t _Z41__static_initialization_and_destruction_0ii > 00000000 T _Z8test_objv > U _ZNSolsEPFRSoS_E > U _ZNSolsEi > U _ZNSt8ios_base4InitC1Ev > U _ZNSt8ios_base4InitD1Ev > U _ZSt4cout > U _ZSt4endlIcSt11char_traitsIcEERSt13basic_ostreamIT_T0_ES6_ > 00000004 b _ZStL8__ioinit > U _ZStlsISt11char_traitsIcEERSt13basic_ostreamIcT_ES5_PKc > U __cxa_atexit > U __dso_handle > U __gxx_personality_v0 > 00000000 B global_def > > > ruben-at-www2:/usr/local/apache/htdocs/nylxs/docs/workshops/scope> nm scope2.o > 000000c7 t _GLOBAL__I_global_def > 00000087 t _Z41__static_initialization_and_destruction_0ii > 00000000 T _Z9test_obj2v > U _ZNSolsEPFRSoS_E > U _ZNSolsEi > U _ZNSt8ios_base4InitC1Ev > U _ZNSt8ios_base4InitD1Ev > U _ZSt4cout > U _ZSt4endlIcSt11char_traitsIcEERSt13basic_ostreamIT_T0_ES6_ > 00000004 b _ZStL8__ioinit > U _ZStlsISt11char_traitsIcEERSt13basic_ostreamIcT_ES5_PKc > U __cxa_atexit > U __dso_handle > U __gxx_personality_v0 > 00000000 B global_def > > ruben-at-www2:/usr/local/apache/htdocs/nylxs/docs/workshops/scope> nm scope_main.o > 000000d3 t _GLOBAL__I_global_def > 00000093 t _Z41__static_initialization_and_destruction_0ii > U _Z8test_objv > U _Z9test_obj2v > U _ZNSolsEPFRSoS_E > U _ZNSolsEi > U _ZNSt8ios_base4InitC1Ev > U _ZNSt8ios_base4InitD1Ev > U _ZSt4cout > U _ZSt4endlIcSt11char_traitsIcEERSt13basic_ostreamIT_T0_ES6_ > 00000004 b _ZStL8__ioinit > U _ZStlsISt11char_traitsIcEERSt13basic_ostreamIcT_ES5_PKc > U __cxa_atexit > U __dso_handle > U __gxx_personality_v0 > 00000000 B global_def > 00000000 T main > > Here you can see that all three ojects made room for the symbol > global_def. I just don't know what the left colomn means, and the man > page for nm is not helpful. > > > > > > > > On Fri, Feb 12, 2010 at 11:35:23AM -0500, Chris Knadle wrote: > > On Friday 12 February 2010 03:00:23 Chris Knadle wrote: > > > On Thursday 11 February 2010 19:24:44 Ruben Safir wrote: > > > > On Thu, Feb 11, 2010 at 07:01:11PM -0500, Ajai Khattri wrote: > > > > > On Thu, 11 Feb 2010, Ruben Safir wrote: > > > > > > Anyone have any constructive insight on this conversation I had with > > > > > > a friend? > > > > > > > > > > I dont see what the problem is. If you're linking to code that is > > > > > outside the current file you must tell the compiler that it is defined > > > > > EXTERNally. > > > > > > > > > > Often when your code is spread across several files, you might want to > > > > > refer to symbols defined in other files or other libraries, so you must > > > > > declare them ahead of your code. > > > > > > > > Its the idea that if you define the var (that is, not use the extern > > > > keyword), that it can create a problem that is bothering me and getting > > > > under my skin. > > > > I've created a C++ program to illustrate, as well as to test the way I thought > > this worked. > > > > //================================== > > //file extern_test_1.cpp > > > > #include > > > > using namespace std; > > > > int global_var=0; > > void external_increment(void); // extern funct to increment global_var by 1 > > > > void local_increment_10(void) > > { > > global_var += 10; > > cout << global_var << "\t after +10 locally" << endl; > > } > > > > int main(void) > > { > > for (int x=0; x<4; x++) { > > local_increment_10(); // global_var += 10 > > external_increment(); // global_var += 1 > > external_increment(); // global_var += 1 > > } > > cout << "ending global_var: " << global_var << endl; > > return 0; > > } > > //================================== > > > > > > > > //================================== > > // file extern_test_2.cpp > > > > #include > > > > using namespace std; > > > > extern int global_var; > > > > void external_increment(void) > > { > > global_var += 1; > > cout << global_var << " \t after +1 externally" << endl; > > } > > //================================== > > > > > > > > Compiled via the command: > > g++ extern_test_1.cpp extern_test_2.cpp -o extern_test > > > > > > > > Notes: > > - Leaving out the 'extern' keyword in extern_test_2.cpp causes > > a compile error. (This is a good thing!) > > > > - In the function prototype for external_increment() in > > extern_test_1.cpp I didn't add the 'extern' keyword because I > > wanted to demonstrate that for functions (only) the 'extern' > > keyword is optional in C++, but it should /should/ be added > > there for human readability. The compiler may be able to > > figure out the function is external, but I wouldn't want to > > have to... > > > > - Global variables should be avoided where possible > > > > -- Chris > > > > -- > > > > Chris Knadle > > Chris.Knadle-at-coredump.us
|
|