-1

I'm programming in C for firmware.

I have a header file: extern.h:

extern int x;

And I have file1.c:

#include"extern.h"
//----------foo1 gives value to x------------------------

foo1(void)
{
    int x=200;  
}  

Now I have foo2 in file2.c

#include"extern.h"

foo2(void)
{
    int x;
    printf("%d",x);
}  

And finally in main.c

#include"extern.h"

void main()
{
    foo1();
    foo2();  
}

What could be the problem if get junk values in execution? I trust the value of the variable must be 200.

I did a similar thing via mplab c18 and instead of printf in foo2.c, I did a transmission to the GUI function in foo2.c and it shows random int values in thousands and ten thousands..completely not related to the 200 that I gave.

And when i did initialize 'x' as

   foo2(void)
   {
        int x;
   }

It again shows random value in thousands.

I trust this not a problem with the coding i have done as it must transmit 200.

Note:

But on counter of that if initialize and transmit in foo2.c then the values are displayed correctly.

Where should I look for bugs: in the GUI or in the Firmware?

David d C e Freitas
  • 7,481
  • 4
  • 58
  • 67
Rookie91
  • 257
  • 3
  • 13

3 Answers3

1

When you say extern int x, it means that it is a global variable which is going to be defined in some other .c file. The local variables you have defined in foo1 and foo2 have precedence over the global extern variable. In foo1 the value of x will be 200 and in foo2 the value of x can be any value depending on what was there on the stack. Also I do not see where you have actually defined x to be a global variable. That is missing too.

user376507
  • 2,004
  • 1
  • 19
  • 31
  • so the data on foo2 can not be 200 right.even if include the headerfile right.And how should i make it 200?.By omitting declaration inside foo2? – Rookie91 Feb 27 '14 at 04:14
  • Yes, you should remove the int declaration of x inside foo2 if you want the global variable x to take effect inside foo2. But you have to somewhere define x to be a global variable in one of the .c file which is also missing in the code which you have shown. – user376507 Feb 27 '14 at 04:21
  • when i remove x, the compiler c18 says so "Error - could not find definition of symbol 'x' in file './build/default/production/main.o'." – Rookie91 Feb 27 '14 at 04:33
  • 1
    You need to define it as a global variable in one of your .c files. Include "int x" before your `void main()` – user376507 Feb 27 '14 at 04:48
1

foo1() -> does nothing

foo2() -> declares a variable x, which is UNDEFINED (no value has been set to it), so it could be anything.

Variables declared like int x; only have a lifetime of the scope they are in, i.e. you can't use the same name everywhere and expect it will map to the same variable.

If your variable is a global extern, don't redeclare it in the local foo functions you have.

See also How do I use extern to share variables between source files?

Community
  • 1
  • 1
David d C e Freitas
  • 7,481
  • 4
  • 58
  • 67
1

When you place the line extern int x; in your extern.h file, what you're stating is that there exists an x somewhere but not here (well, not here unless you also have an int x; as well in the same scope).

In other words, it's a declaration that something exists rather than a definition that creates that something. So, without a definition, that particular x is never created.

In both your foo1() and foo2() functions, you do create something called x, however it's not the same x as the one you've declared in extern.h: it has different scope.

Both the x in foo1() and foo2() (and they are distinct variables, not the same one) are local to the function they're defined in. Hence foo1() creates its x, sets the value of it to 200 then throws that away on exit.

foo2(), on the other hand, creates its x with an arbitrary value and then prints it (hence your "junk value" comment).

That explains the behaviour you're seeing, now how to fix that. The way this is normally done is to define the variable somewhere (only once) and declare it wherever it's used, something like:

extern.h:
    extern int x;         // declare it
    void foo1(void);
    void foo2(void);

foo1.c:
    #include "extern.h"   // declare x via the header

    void foo1(void) {
        x = 200;          // set x, note: no int at start of line
                          //   since that would create a NEW x.
    }

foo2.c:
    #include <stdio.h>
    #include "extern.h"   // declare x via the header

    void foo2(void) {
        printf "%d\n", x);  // again, no "int x;" since that would
                            //   create a NEW x.
    }

main.c:
    #include "extern.h"   // declare in the header
    int x;                // and define it.

    int main (void) {
        foo1();
        foo2();
        return 0;
    }

So the "global" x exists in main.c (though you could put it in any of the C files, as long as it's only in one of them). The fact that both foo1.c and foo2.c include the extern.h header that declares the existence of x means that they'll be able to find it.

By ensuring that neither foo1() nor foo2() define another x in local scope (by using int x; or int x = something;), they'll use the x at the next outer scope (i.e, the one in main.c).


When you define an inner-scope variable of the same name as an outer scope one, the former "hides" (or "shadows") the latter. For example, the code:

#include <stdio.h>
int main (void) {
    int x = 42;
    printf ("A: %8d\n", x);
    {
        int x = 314159;
        printf ("B: %8d\n", x);
    }
    printf ("C: %8d\n", x);
    return 0;
}

will output:

A:       42
B:   314159
C:       42

as the inner braces create a new x within that scope. And, when the scope ends, the x you see then is the original one.

paxdiablo
  • 854,327
  • 234
  • 1,573
  • 1,953
  • i did the same but unfortunalely I could not get the results. I got this error from the c18 compiler "Error - could not find definition of symbol 'x' in file './build/default/production/main.o'." – Rookie91 Feb 27 '14 at 04:51
  • 1
    @Rookie91: then you haven't defined it. I suggest you look at the code again, specifically the bit in `main.c` that says `int x;`. – paxdiablo Feb 27 '14 at 04:53
  • if i declare that as extern in header file. Why is it necessary that i have to declare it as global int 'x' so in main.c – Rookie91 Feb 27 '14 at 05:37
  • 1
    @Rookie, you may want to read the answer again. The thing in the header file is a declaration, it does _not_ create `x`. `int x;` in `main.c` is a **definition** that _does_ create `x`. You must _define_ it somewhere. – paxdiablo Feb 27 '14 at 05:38
  • Thanks a lot for clearing my doubt and for your time :) – Rookie91 Feb 27 '14 at 05:40
  • @Rookie, no probs, glad I could help. – paxdiablo Feb 27 '14 at 05:40