38

How can I access a shadowed global variable in C? In C++ I can use :: for the global namespace.

vitaly.v.ch
  • 2,485
  • 4
  • 26
  • 36
  • 14
    The solution is to avoid shadowing variables... inevitably it will mess you up... (I speak from experience) – Spudd86 Jun 14 '10 at 20:42

6 Answers6

56

If your file-scope variable is not static, then you can use a declaration that uses extern in a nested scope:

int c;

int main() {
    {
        int c = 0;
        // now, c shadows ::c. just re-declare ::c in a 
        // nested scope:
        {
            extern int c;
            c = 1;
        }
        // outputs 0
        printf("%d\n", c);
    }
    // outputs 1
    printf("%d\n", c);
    return 0;
}

If the variable is declared with static, i don't see a way to refer to it.

Johannes Schaub - litb
  • 496,577
  • 130
  • 894
  • 1,212
  • 1
    If it's static, add another static variable `static int *address_of_c=&c;` at the same scope as `c` and then use `*address_of_c` to access it. – R.. GitHub STOP HELPING ICE Sep 21 '11 at 04:34
  • @R.. I understood it as a challenge to access "::c" without adding things to global scope. – Johannes Schaub - litb Sep 21 '11 at 10:31
  • If the variable is file static (so the first line is `static int c = 42;`, for example), then the `extern` in the innermost block says "the variable `c` defined outside the the current function, and refers to the file scope variable. Or, at least, that's how GCC 4.8.2 interprets it. – Jonathan Leffler Jan 13 '14 at 06:23
  • @JohannesSchaub-litb C doesn't have `::`? And according to [this answer](http://stackoverflow.com/a/28300345/689991) it's impossible to access shadowed variable in C. – Quazi Irfan Feb 13 '17 at 06:26
  • @iam i am not sure what you are saying. Whether or not the other answer is correct depends on what he means by "refer to the identifier". In my answer, I declare "c" again and use that local blockscope identifier to refer to the object that was declared at filescope. Perhaps he/she is not aware of my "trick", or he simply counts my trick as not refering to the filescope identifier. The refering in my code is done by linking, not by lookup. You best ask him/her directly for what he/her means to say – Johannes Schaub - litb Feb 13 '17 at 10:36
  • Hi, late for the party. I'm not sure, but if `c` is static, isn't it accessible to the whole file (but not from other files)? Sorry I'm new to C so probably I'm wrong... – Nicholas Humphrey Aug 25 '19 at 20:37
  • @Nicholas the `extern int c;` declares the variable as `extern`, which is the opposite of `static`. That's the reason it doesn't work with `static` variables. The keyword `static` within a function has a different meaning, so we cannot apply it here. – Johannes Schaub - litb Aug 26 '19 at 06:02
  • @JohannesSchaub-litb, no `extern` only declares that a symbol has linkage. If no `static` declaration has been seen before that linkage is extern, if it has the linkage is intern. – Jens Gustedt Oct 30 '20 at 09:59
  • @Jens thanks for the clarification. If you are sure of that, you can change my answer to remove the last statement or amend as needed. – Johannes Schaub - litb Oct 31 '20 at 18:31
  • 1
    @JohannesSchaub-litb, yes, this is 6.2.2 p4: ... *if the prior declaration specifies internal or external linkage, the linkage of the identifier at the later declaration is the same as the linkage specified at the prior declaration.* – Jens Gustedt Nov 01 '20 at 21:31
26

There is no :: in c but you can use a getter function

#include <stdio.h>

int L=3;

inline int getL()
{
   return L;
}

int main();
{
   int L = 5;

   printf("%d, %d", L, getL());
}
Dutow
  • 5,638
  • 1
  • 30
  • 40
  • I have tried to edit the answer, but edit queue is full!!. So I am adding the corrected code here: `#include int L=3; static inline int getL() { return L; } int main() { int L = 5; printf("%d, %d", L, getL()); }` – B_San May 09 '22 at 19:07
5

If you are talking about shadowed global var, then (on Linux) you can use dlsym() to find an address of the global variable, like this:

int myvar = 5;    // global

{
    int myvar = 6;    // local var shadows global
    int *pglob_myvar = (int *)dlsym(RTLD_NEXT, "myvar");
    printf("Local: %d, global: %d\n", myvar, *pglob_myvar);
}

If you want your code to look sexy, use macro:

#define GLOBAL_ADDR(a,b)  b =(typeof(b))dlsym(RTLD_NEXT, #a)
...
int *pglob_myvar;
GLOBAL_ADDR(myvar, pglob_myvar);
...
qrdl
  • 34,062
  • 14
  • 56
  • 86
2

Depending on what you call shielded global variable in C, different answers are possible.

If you mean a global variable defined in another source file or a linked library, you only have to declare it again with the extern prefix:

extern int aGlobalDefinedElsewhere;

If you mean a global variable shadowed (or eclipsed, choose the terminology you prefer) by a local variable of the same name), there is no builtin way to do this in C. So you have either not to do it or to work around it. Possible solutions are:

  • getter/setter functions for accessing global variable (which is a good practice, in particular in multithreaded situations)

  • aliases to globals by way of a pointer defined before the local variable:

    int noName;
    {
        int * aliasToNoName = &noName; /* reference to global */
        int noName;                    /* declaration of local */
        *aliasToNoName = noName;       /* assign local to global */
    }
    
mouviciel
  • 66,855
  • 13
  • 106
  • 140
1

Yet another option is to reference the global before defining your local, or at least get a pointer to it first so you can access it after defining your local.

#include <stdio.h>

int x = 1234;
int main()
{
   printf("%d\n",x); // prints global
   int x = 456;
   printf("%d\n",x); // prints local
}
David Neiss
  • 8,161
  • 2
  • 20
  • 21
1

what is a "shielded global variable" in pure C?

in C you have local variables, file local/global variables (static) and global variables (extern)

so file1.c:
int bla;

file2.c
extern int bla;
Peter Miehle
  • 5,984
  • 2
  • 38
  • 55