Tuesday, February 8, 2011

Finding the name of a variable in C

I was asked a question in C last night and I did not know the answer since I have not used C much since college so I thought maybe I could find the answer here instead of just forgetting about it.

If a person has a define such as:

"#define count 1"

Can that person find the variable name "count" using the 1 that is inside it?

I did not think so since I thought the count would point to the 1 but do not see how the 1 could point back to count.

  • What do you mean by "finding"?

    The line

    #define count 1
    

    defines a symbol "count" that has value 1.

    The first step of the compilation process (called preprocessing) will replace every occurence of the symbol count with 1 so that if you have:

    if (x > count) ...
    

    it will be replaced by:

    if (x > 1) ...
    

    If you get this, you may see why "finding count" is meaningless.

    From Remo.D
  • #define is a pre-processor directive, as such it is not a "variable"

    From Cade Roux
  • C defines are a pre-processor directive, not a variable. The pre-processor will go through your C file and replace where you write count with what you've defined it as, before compiling. Look at the obfuscated C contest entries for some particularly enlightened uses of this and other pre-processor directives.

    The point is that there is no 'count' to point at a '1' value. It just a simple/find replace operation that happens before the code is even really compiled.

    I'll leave this editable for someone who actually really knows C to correct.

    From JeeBee
  • Can that person find the variable name "count" using the 1 that is inside it?

    No

    From finalman
  • The simple answer is no they can't. #Defines like that are dealt with by the preprocessor, and they only point in one direction. Of course the other problem is that even the compiler wouldn't know - as a "1" could point to anything - multiple variables can have the same value at the same time.

    From robintw
  • As I'm sure someone more eloquent and versed than me will point out #define'd things aren't compiled into the source, what you have is a pre-processor macro which will go through the source and change all instance of 'count' it finds with a '1'.

    However, to shed more light on the question you were asked, because C is a compiled language down to the machine code you are never going to have the reflection and introspection you have with a language like Java, or C#. All the naming is lost after compilation unless you have a framework built around your source/compiler to do some nifty stuff.

    Hope this helps. (excuse the pun)

    paxdiablo : Where's the pun???
    PintSizedCat : It was a reference to a Question I had just been answering about the use of 'this' in a constructor.
    Nathan Fellman : but you didn't add the link
  • What you have there is actually not a variable, it is a preprocessor directive. When you compile the code the preprocessor will go through and replace all instaces of the word 'count' in that file with 1.

    You might be asking if I know 1 can I find that count points to it? No. Because the relationship between variables names and values is not a bijection there is no way back. Consider

    int count = 1;
    int count2 = 1;
    

    perfectly legal but what should 1 resolve to?

    From stimms
  • Building on @Cade Roux's answer, if you use a preprocessor #define to associate a value with a symbol, the code won't have any reference to the symbol once the preprocessor has run:

    #define COUNT (1)
    ...
    int myVar = COUNT;
    ...
    

    After the preprocessor runs:

    ...
    int myVar = (1);
    ...
    

    So as others have noted, this basically means "no", for the above reason.

  • In general, no.

    Firstly, a #define is not a variable, it is a compiler preprocessor macro.

    By the time the main phase of the compiler gets to work, the name has been replaced with the value, and the name "count" will not exist anywhere in the code that is compiled.

    For variables, it is not possible to find out variable names in C code at runtime. That information is not kept. Unlike languages like Java or C#, C does not keep much metadata at all, in compiles down to assembly language.

    From Anthony
  • Directive starting with "#" are handled by the pre-processor which usually does text substitution before passing the code to the 'real' compiler. As such, there is no variable called count, it's as if all "count" strings in your code are magically replaced with the "1" string.

    So, no, no way to find that "variable".

    From paxdiablo
  • In case of a macro this is preprocessed and the resulting output is compiled. So it is absolutely no way to find out that name because after the preprocessor finnishes his job the resulting file would contain '1' instead of 'count' everywhere in the file.

    So the answer is no.

  • If they are looking at the C source code (which they will be in a debugger), then they will see something like

    int i = count;
    

    at that point, they can search back and find the line

    #define count 1
    

    If, however, all they have is variable iDontKnowWhat, and they can see it contans 1, there is no way to track that back to 'count'.

    Why? Because the #define is evaluated at preprocessor time, which happens even before compilation (though for almost everyone, it can be viewed as the first stage of compilation). Consequently the source code is the only thing that has any information about 'count', like knowing that it ever existed. By the time the compiler gets a look in, every reference to 'count' has been replaced by the number '1'.

  • It's not a pointer, it's just a string/token substitution. The preprocessor replaces all the #defines before your code ever compiles. Most compilers include a -E or similar argument to emit precompiled code, so you can see what the code looks like after all the #directives are processed.

    More directly to your question, there's no way to tell that a token is being replaced in code. Your code can't even tell the difference between (count == 1) and (1 == 1).

    If you really want to do that, it might be possible using source file text analysis, say using a diff tool.

    From davenpcj
  • One trick used in C is using the # syntax in macros to obtain the string literal of the of the macro parameter.

    #define displayInt(val) printf("%s: %d\n",#val,val)
    #define displayFloat(val) printf("%s: %d\n",#val,val)
    #define displayString(val) printf("%s: %s\n",#val,val)
    
    int main(){
      int foo=123;
      float bar=456.789;
      char thud[]="this is a string";
    
      displayInt(foo);
      displayFloat(bar);
      displayString(thud);
    
      return 0;
    }
    

    The output should look something like the following:

    foo: 123
    bar: 456.789
    thud: this is a string
    
  • The person asking the question (was it an interview question?) may have been trying to get you to differentiate between using #define constants versus enums. For example:

    #define ZERO 0
    #define ONE 1
    #define TWO 2
    

    vs

    enum {
      ZERO,
      ONE,
      TWO
    };
    

    Given the code:

    x = TWO;
    

    If you use enumerations instead of the #defines, some debuggers will be able to show you the symbolic form of the value, TWO, instead of just the numeric value of 2.

    From Trent
  • count isn't a variable. It has no storage allocated to it and no entry in the symbol table. It's a macro that gets replaced by the preprocessor before passing the source code to the compiler.

    On the off chance that you aren't asking quite the right question, there is a way to get the name using macros:

    #define SHOW(sym) (printf(#sym " = %d\n", sym))
    #define count 1
    
    SHOW(count); // prints "count = 1"
    

    The # operator converts a macro argument to a string literal.

  • #define count 1 is a very bad idea, because it prevents you from naming any variables or structure fields count.

    For example:

    void copyString(char* dst, const char* src, size_t count) {
       ...
    }
    

    Your count macro will cause the variable name to be replaced with 1, preventing this function from compiling:

    void copyString(char* dst, const char* src, size_t 1) {
       ...
    }
    
    From bk1e

0 comments:

Post a Comment