Thread: global variable confusion

  1. #1
    Registered User
    Join Date
    Dec 2007
    Posts
    67

    global variable confusion

    Code:
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <ctype.h>
    #include <time.h>
    
    #define LEN 20		/* word array size */
    #define HASHSIZE 12289		/* hash table size */
    
    typedef struct L { char k[LEN]; struct L *next; } List;		/* list element */
    
    struct hash_list { char *word; struct hash_list *next; } hash_list;		/* hash table element */
    does defining LEN and HASHSIZE like that make them global variables?? i don't think it does but i am not sure

  2. #2
    Beautiful to C Aia's Avatar
    Join Date
    Jun 2007
    Posts
    124
    They are not variables at all. They are pre-process directives. You can considerate them as constant values.
    Last edited by Aia; 01-24-2008 at 05:47 PM.

  3. #3
    Frequently Quite Prolix dwks's Avatar
    Join Date
    Apr 2005
    Location
    Canada
    Posts
    8,057
    When the processor sees a line beginning with '#'[1], it processes the command on that line. The preprocessor can do quite a few different things. For example, when it sees "#include <stdio.h>", it opens the file stdio.h and puts that data verbatim into your program where the #include statement was.

    When it sees a #define statement, it basically does a search-and-replace throughout your source code for that identifier. (It doesn't substitute inside strings, but otherwise it's basically S&R.) This means that #define values can be anything, not just ints or whatever:
    Code:
    #define SEMICOLON ;
    #define TRICKYCODE do { puts("tricky); } while(0)
    The bad thing about #defines is that they have no concept of scope or semantic meanings. If you use something like this by accident
    Code:
    #define X 10
    
    int X = 10;
    the compiler will see
    Code:
    int 10 = 10;
    and you'll get a nasty, likely indecipherable error.

    I prefer to use the enum-hack and/or const-ant values myself.

    [1] The first non-whitespace character on the line must be a '#'.
    dwk

    Seek and ye shall find. quaere et invenies.

    "Simplicity does not precede complexity, but follows it." -- Alan Perlis
    "Testing can only prove the presence of bugs, not their absence." -- Edsger Dijkstra
    "The only real mistake is the one from which we learn nothing." -- John Powell


    Other boards: DaniWeb, TPS
    Unofficial Wiki FAQ: cpwiki.sf.net

    My website: http://dwks.theprogrammingsite.com/
    Projects: codeform, xuni, atlantis, nort, etc.

  4. #4
    Registered User
    Join Date
    Jun 2005
    Posts
    6,815
    That depends on how you use them, Aia. In reality they are not constants: they are macros that happen to expand to particular text. After the macro is #defined, the preprocessor substitutes every instance of the macro name (eg LEN) with it's replacement text.

    In agentsmith's example, there are no constants or variables named LEN or HASHSIZE seen by the compiler.

    For example, the typedef that declares List is effectively seen by the compiler as;
    Code:
    typedef struct L { char k[20]; struct L *next; } List;
    Unlike a declaration of a constant, a macro can be redefined. For example;
    Code:
    int main()
    {
    #define LEN 20
        int a[LEN];
    
    #undef LEN
    #define LEN 50
        int b[LEN];
    
        for (i = 0; i < LEN; ++i)  a[i] = 42;
        return 0;
    }
    will declare a to be an array of 20 elements and b to be an array of 50 elements. The loop also invokes undefined behaviour becase it sets 50 elements of the array a, which only has 20 elements.

  5. #5
    Madly in anger with you
    Join Date
    Nov 2005
    Posts
    211
    Quote Originally Posted by dwks View Post
    The bad thing about #defines is that they have no concept of scope or semantic meanings. If you use something like this by accident
    Code:
    #define X 10
    
    int X = 10;
    the compiler will see
    Code:
    int 10 = 10;
    and you'll get a nasty, likely indecipherable error.

    I prefer to use the enum-hack and/or const-ant values myself.

    [1] The first non-whitespace character on the line must be a '#'.
    indeed, be careful when using #define with typedef, as they appear to be handled in the same way by the preprocessor (at least, with MSVC). about a month ago I was stumped with a hard to find error because of this. if you typedef a new type with the name of a constant that you didn't want to #define, you might end up with some unexpected results.

  6. #6
    Frequently Quite Prolix dwks's Avatar
    Join Date
    Apr 2005
    Location
    Canada
    Posts
    8,057
    Actually, what happens is that the preprocessor does a search-and-replace over everything, including typedef names and variables and functions and all other identifiers.

    Preprocessor directives such as macros are handled by the preprocessor, which is typically separate from the compiler proper. Typedefs are handled by the compiler itself, like enums. This is why they're preferable: the compiler can give you proper errors for misusing these types, and the compiler can even store relevant debugging information into a program such that the debugger can access this information as well. enum values are a sight for sore eyes in a debugger compared with literal numbers. And have you ever tried debugging a macro, especially a really, really long one? Ouch.
    dwk

    Seek and ye shall find. quaere et invenies.

    "Simplicity does not precede complexity, but follows it." -- Alan Perlis
    "Testing can only prove the presence of bugs, not their absence." -- Edsger Dijkstra
    "The only real mistake is the one from which we learn nothing." -- John Powell


    Other boards: DaniWeb, TPS
    Unofficial Wiki FAQ: cpwiki.sf.net

    My website: http://dwks.theprogrammingsite.com/
    Projects: codeform, xuni, atlantis, nort, etc.

  7. #7
    Fountain of knowledge.
    Join Date
    May 2006
    Posts
    794
    Quote Originally Posted by agentsmith View Post
    Code:
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <ctype.h>
    #include <time.h>
    
    #define LEN 20		/* word array size */
    #define HASHSIZE 12289		/* hash table size */
    
    typedef struct L { char k[LEN]; struct L *next; } List;		/* list element */
    
    struct hash_list { char *word; struct hash_list *next; } hash_list;		/* hash table element */
    does defining LEN and HASHSIZE like that make them global variables?? i don't think it does but i am not sure
    Firstly as has been said they are not variables, they are definition of a value, hence the name #def (define as).

    Mind you do bring up an issue of the scope of the definition, whether it is local to the file it is in or global.

    I mean you could define LEN as 20 in one FILE and then define it as 999 in another file!!
    (at least I think you can anyway, if you compile them seperately, although it is more normal to put definitions like that in a header file and include that in each file to have a 'global' definiton. I think it would work if you compile them seperately then link them later, eitherway I am sure the compiler/linker will let know if it has a problem with it!

    Usually all my code is in one file so I don't have to think about such things but I have worked on a project where finding which definitions to include is harder than writing the code!!

    You can end up including everything!!!

    This is my opinon, I am not a C compiler.

  8. #8
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    Quote Originally Posted by esbo View Post
    I mean you could define LEN as 20 in one FILE and then define it as 999 in another file!!
    You could do that if one variable was global and one was local (or both are local), or if one or two of them were defines.
    Otherwise you end up with a linking error.
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  9. #9
    Frequently Quite Prolix dwks's Avatar
    Join Date
    Apr 2005
    Location
    Canada
    Posts
    8,057
    Well, not exactly. You can have static global variables, which are limited to the scope of a file. You could have one of these variables of the same name in two different source files.
    dwk

    Seek and ye shall find. quaere et invenies.

    "Simplicity does not precede complexity, but follows it." -- Alan Perlis
    "Testing can only prove the presence of bugs, not their absence." -- Edsger Dijkstra
    "The only real mistake is the one from which we learn nothing." -- John Powell


    Other boards: DaniWeb, TPS
    Unofficial Wiki FAQ: cpwiki.sf.net

    My website: http://dwks.theprogrammingsite.com/
    Projects: codeform, xuni, atlantis, nort, etc.

  10. #10
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    Oooh, another exception. We like exceptions, don't we?
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  11. #11
    Frequently Quite Prolix dwks's Avatar
    Join Date
    Apr 2005
    Location
    Canada
    Posts
    8,057
    Eh, you want pedantic definitions?
    You could do that if one variable was global and one was local (or both are local), or if one or two of them were defines.
    It would work with two local variables of the same name, it's true, but not two local variables with the same name in the same scope. Then you get a compiler error, "`foo' redefined" or some such, not a linker error.
    dwk

    Seek and ye shall find. quaere et invenies.

    "Simplicity does not precede complexity, but follows it." -- Alan Perlis
    "Testing can only prove the presence of bugs, not their absence." -- Edsger Dijkstra
    "The only real mistake is the one from which we learn nothing." -- John Powell


    Other boards: DaniWeb, TPS
    Unofficial Wiki FAQ: cpwiki.sf.net

    My website: http://dwks.theprogrammingsite.com/
    Projects: codeform, xuni, atlantis, nort, etc.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Regarding global variable.
    By sunny_master_07 in forum C++ Programming
    Replies: 1
    Last Post: 07-29-2008, 06:38 AM
  2. Global variable in shared library
    By krock923 in forum C Programming
    Replies: 5
    Last Post: 01-11-2008, 04:56 PM
  3. static class variable vs. global variable
    By nadamson6 in forum C++ Programming
    Replies: 18
    Last Post: 09-30-2005, 03:31 PM
  4. Global variable question
    By csisz3r in forum C Programming
    Replies: 10
    Last Post: 09-19-2005, 07:19 AM
  5. Global variable???
    By loopy in forum C Programming
    Replies: 13
    Last Post: 06-09-2002, 03:08 PM