need a help on extern variable check

Hello All,

I am working on a problem, where i have to put a check on an extern variable(flag) and on basis of that check my program could work. The scenario is as following. I have declared an extern variable in ABC.h as "extern uint8 test " and in file ABC.c i am intiallizing it with "extern uint8 test = 1" into a function. In my main file i want to add a check that "if(extern variable int == 1) then perform a function xyz", as my function xyz is dependent on occurence of function in ABC.c.

But however i am getting an error that two instances of a variable are not allowed or variable is defined two times. Kindly guide me, what other procedure could be adopted, where a check could be implemented to check the gloabl variable defined in another file.

Best Regards
Rebelsoul

Comments

  • First, be aware that using extern means you have a flawed program design. There is never a need to use extern or global variables in a C program. A better way in this case might have been to declare a static variable in ABC.c that keeps track of whatever flag you need.

    The reason you get errors is because extern doesn't actually allocate a variable. So you can't write "extern int x = something" unless "int x;" exists elsewhere in the code.
  • Dear Lundin,

    > There is never a need to use extern or global variables in a C program.

    Which reference do you have this from? And is this also true for C++?

    Thanks, Bilderbikkel
  • [color=Blue]What Lundin means is that using 'extern' is not a best practice in C/C++. I can agree with that. It is possible to create large program without using any of global variables, however, doing so will result in a slight overhead. You simply have to pass the global variables object to each function or object it needs. Let me demonstrate it in C:[/color]
    [code]
    [color=Green]// -------------------------------------------------------------------------[/color]
    typedef struct
    {
    int Member1;
    char Member2 [256];
    [color=Green]// anything else ... pointers... etc.[/color]
    }
    GLOBALS;

    [color=Green]// -------------------------------------------------------------------------[/color]
    GLOBALS* InitGlobals ()
    {
    GLOBALS* pApp = (GLOBALS*) calloc (1, sizeof (GLOBALS));
    if (pApp != NULL)
    {
    [color=Green]// Initialize members of GLOBALS.
    // 'calloc' will set all members to zero and
    // here we need only to set non-zero members.[/color]
    }
    return pApp;
    }

    [color=Green]// -------------------------------------------------------------------------[/color]
    void RunApplication (GLOBALS* pApp)
    {
    }

    [color=Green]// -------------------------------------------------------------------------[/color]
    int main ()
    {
    GLOBALS* pApp = InitGlobals ();
    if (pApp != NULL)
    {
    RunApplication (pApp);
    free (pApp);
    }
    else printf ("

    Unable to initialize application data.");
    return 0;
    }
    [/code]
    [color=Blue]Now, we need to keep passing 'pApp' to every function we create/call inside RunApplication(). There is another way, however - using static variable:[/color]
    [code]
    [color=Green]// -------------------------------------------------------------------------
    // File: GLOBALS.H
    // -------------------------------------------------------------------------[/color]

    typedef struct
    {
    int Member1;
    char Member2 [256];
    [color=Green]// anything else ... pointers... etc.[/color]
    }
    GLOBALS;

    [color=Green]// -------------------------------------------------------------------------
    // PROTOTYPES:
    // -------------------------------------------------------------------------[/color]
    bool InitGlobals ();
    void ReleaseGlobals ();
    GLOBALS* GetVars ();




    [color=Green]// -------------------------------------------------------------------------
    // File: GLOBALS.C
    // -------------------------------------------------------------------------[/color]

    static GLOBALS* st_pApp = NULL;

    [color=Green]// -------------------------------------------------------------------------[/color]
    bool InitGlobals ()
    {
    st_pApp = (GLOBALS*) calloc (1, sizeof (GLOBALS));
    if (st_pApp != NULL)
    {
    [color=Green]// Initialize members of GLOBALS.
    // 'calloc' will set all members to zero and
    // here we need only to set non-zero members.[/color]

    return true;
    }
    return false;
    }

    [color=Green]// -------------------------------------------------------------------------[/color]
    void ReleaseGlobals ()
    {
    free (st_pApp);
    }

    [color=Green]// -------------------------------------------------------------------------[/color]
    GLOBALS* GetVars ()
    {
    return st_pApp;
    }

    [color=Green]// -------------------------------------------------------------------------
    // File: MAIN.C
    // -------------------------------------------------------------------------[/color]

    #include "GLOBALS.H"

    [color=Green]// -------------------------------------------------------------------------[/color]
    void RunApplication ()
    {
    [color=Green]// Now each function can move the pointer
    // into its local area for performance.[/color]

    GLOBALS* pApp = GetVars ();

    [color=Green]// Use 'pApp' to do anything with globals
    // ...[/color]
    }

    [color=Green]// -------------------------------------------------------------------------[/color]
    int main ()
    {
    if (InitGlobals ())
    {
    RunApplication ();
    ReleaseGlobals ();
    }
    else printf ("

    Unable to initialize application data.");
    return 0;
    }
    [/code]
    [color=Blue]In this scenario, no passing the pointer around, but each file using it should include "GLOBALS.H" and use GetVars() to access the static pointer in any function. Strictly speaking, that static pointer is a global variable already in a sense that it is declared in data section of the EXE file. The first solution does not do that - it is pure in that sense. ;-)

    It is easy enough to port both of these solutions to C++.[/color]
  • Thanks AsmGuru62 for your reply,

    Your example is fine, but what I would really like to see is a reference to the literature.

    Have you got one?

    See ya, Bilderbikkel
  • Well... try to post a case where global variables are a must, and I'm confident I will shoot it down :)

    I can't refer to any books. As others can tell, I am very sceptical against C books, since roughly 50% of the books on the market seems to be written by hobbyists that don't even know the C standard.

    I can however refer to the coding standard MISRA-C:2004 that bans globals entirely in an advisory rule. I can't cite it because of copyright reasons.

    The less acknowledged CERT C standard is a bit more meek, and only advises against it without banning it, [link=https://www.securecoding.cert.org/confluence/display/seccode/DCL15-C.+Declare+file-scope+objects+or+functions+that+do+not+need+external+linkage+as+static]here[/link].

    There are three cases in C I can think of where you want to place a variable at "file scope", ie outside functions:

    1) You want to declare static private variables only available to one code module. This is the most common cause. These aren't considered "global".

    2) You want to communicate with a function that doesn't allow parameter passing, like an interrupt service routine, or some sort of callback function.

    3) You are writing an extermely time-critical realtime application (hostless app or RTOS) and your C compiler doesn't support inlining.


    Case 1 could be something like what Asmguru posted. The common way to declare private variables in C is however:

    [code]static int _something;

    int get_something()
    {
    return _something;
    }[/code]

    This does exactly the same as private in C++, private encapsulation. The only valid argument against this is that the C standard doesn't support function inlining. Most good C compilers do, but perhaps not all. Hence case 3 above.

    And in case 2, you can still declare the variables as static: in fact, you especially don't want any "outsider" to meddle with variables shared by a thread or isr, since those will be extra sensitive in case of re-entrant code.
Sign In or Register to comment.

Howdy, Stranger!

It looks like you're new here. If you want to get involved, click one of these buttons!

Categories