1

I am reading Efficient c++ (older version) and have some doubts. Here, for example, it says:

When you do something like this

#define ASPECT_RATIO 1.653

the symbolic name ASPECT_RATIO may never be seen by the compilers; it may be removed by the preprocessors before the source code ever gets compiled. As a results the ASPECT_RATIO may never get entered to SYMBOLIC_TABLE. It an be confusing if you get an error during compilation involving the constant, because the error message may refer to 1.653 and not ASPECT_RATIO

I don't understand this paragraph.How can anything be removed the preprocessor, just like that. what could be the reasons and how feasible are they in real world.

Thanks

bruceparker
  • 1,235
  • 1
  • 17
  • 33
  • You can see what transformation this has by [having the compiler output the file after preprocessing](http://stackoverflow.com/questions/277258/c-c-source-file-after-preprocessing). – André Caron Jan 12 '12 at 04:39

3 Answers3

3

It's simply a global search and replace of "ASPECT_RATIO" with "1.653" in the file before passing it to the compiler

That's why macros are so dangerous. If you have #define max 123 and a variable int max = 100 the compiler will get int 123 = 100 and you will get a confusing error message

Martin Beckett
  • 94,801
  • 28
  • 188
  • 263
  • I am confused #include #define max 123 int main(){ int max123 = 10; std::cout< – bruceparker Jan 12 '12 at 04:41
  • This is incorrect, the C preprocessor works on tokens, on just any string match. – Alex Jan 12 '12 at 04:46
  • @Leoheart no, its just wrong example. pre-processor deals with tokens, not partial strings. if, in your code, you define `int max` after including iostream, you're likely to get a compilation error of some kind (the kind of error my differ between compilers). – littleadv Jan 12 '12 at 04:46
  • @Alex what is "this" is your statement, my program's result or program OR the example by the Martin? – bruceparker Jan 12 '12 at 04:48
  • @littleadv: I got that. Thanks? But how is that a problem. I mean, if i try to declare two variable even by same name, like for example "max" here. even then that error would come? Am i getting you correct here? – bruceparker Jan 12 '12 at 04:49
  • @Leoheart yes, but depending on compilers, it will not be the same error. The reason is different: in the case of a macro conflicting with your name - your name will be replaced with the macro (if the pre-processor is not smart enough to complain), and then you'll either have a problem, or a bug. If two symbols conflict - you can either have a compilation error or shadowing of one symbol by another in the scope (which, in many cases, is also a bug). – littleadv Jan 12 '12 at 04:52
  • @leoheart - sorry I made a mistake. There are some circumstances with templates where it can replace some bits you really don't expect! – Martin Beckett Jan 12 '12 at 04:59
  • @leohart sorry if that was confusing, I was referring to Martin's example. I meant to say "not" where I said "on". The original answer was incorrect - maximumwidth would not have been replaced by 123imumwidth. It's been corrected now though. – Alex Jan 12 '12 at 06:24
3

I don't understand this paragraph under inverted quotes.How can anything be removed the preprocessor, just like that. what could be the reasons and how feasible are they in real world.

Basically what it describes is exactly how C and C++ pre-processor works. The reason is to replace macros/constants (that are made using the #define directive) with their actual values, instead of repeating the same values over and over again. In C++ it is considered a bad style using C-style macros, but they're supported for C compatibility.

The preprocessor, as the name suggests, runs prior to the actual compilation, and is basically changing the source code as directed through the pre-processor directives (those starting with #). This also includes replacement of the macros with their values, the inclusion of the header files as directed by the #include directive, etc etc.

This is used in order to avoid code repetitions, magic numbers, to share interfaces (header files) and many other useful things.

littleadv
  • 20,100
  • 2
  • 36
  • 50
  • Sorry, but it doesnt answer my question at all. I understand how macros works atleast to some extent, what i dont understand is "How can a defined macro be removed by the preprocessor, just like that. what could be the reasons and how feasible are they in real world"?? – bruceparker Jan 12 '12 at 04:45
  • @Leoheart I though I answered exactly what you asked. How can a defined macro be removed by the pre-processor? By replacement with the value of the macro. I wrote a bit more than just that, but basically - that is how. I also went on and explained the reasons why it is done. What's not clear? I'll clarify. – littleadv Jan 12 '12 at 04:49
  • 1
    @Leoheart: The preprocessor is basically an automated find-and-replace tool that runs before the compiler. When the preprocessor sees `#define ASPECT_RATIO 1.653`, it will from now on replace all instances of `ASPECT_RATIO` it finds with `1.653`. The preprocessor removes `ASPECT_RATIO` from the source code text before feeding it into the compiler, so the compiler never sees it. – In silico Jan 12 '12 at 04:58
  • @littleadv Thanks. I understood now after reading your answer again. I still have this doubt. If it gets replaced, how can it be a problem? and why did the book say "it MAY be removed by the preprocessors before the source code ever gets compiled", when we know for sure that it WILL be removed? Thanks for your patience and answering my question. – bruceparker Jan 12 '12 at 04:59
  • @ In silico : Got it. Thanks. I am still waiting for one doubt which i asked from littleadv – bruceparker Jan 12 '12 at 05:01
  • @Leoheart: As Meyers have pointed out, because the preprocessor removes the name `ASPECT_RATIO` from the source code, if you get an error message around where `ASPECT_RATIO` is used you see `1.653` instead of `ASPECT_RATIO`. That makes debugging way harder because what the compiler sees is different from what you see. What Meyers probably meant by "it MAY be removed..." is that a compiler implementation is free to preserve the preprocessor tokens, perhaps as a way to improve error messages. I haven't seen that happen in practice. – In silico Jan 12 '12 at 05:02
  • @Leoheart depends on the compiler implementation, pre-processor may not physically remove it from the stream passed on, but instead the compiler will do it. I'm not sure if there's an actual requirement in the standard to physically replace, its just the simplest way to do it and the compilers are complicated enough not to chose a complicated solution for this particular functionality. – littleadv Jan 12 '12 at 05:06
1

The pre-processor will replace all instances of the token ASPECT_RATIO that appear in the code with the actual token 1.653 ... thus the compiler will never see the token ASPECT_RATIO. By the time it compiles the code, it only sees the literal token 1.653 that was substituted in by the pre-processor.

Basically the "problem" you will encounter with this approach is that ASPECT_RATIO will not be seen as a symbol by the compiler, thus in a debugger, etc., you can't query the value ASPECT_RATIO as-if it were a variable. It's not a value that will have a memory address like a static const int may have (I say "may", because an optimizing compiler may decide to act like the pre-processor, and optimize-out the need for an explicit memory address to store the constant value, instead simply substituting the literal value where-ever it appears in the code). In a larger function macro it also won't have an instruction address like actual C/C++ function will have, thus you can't set break-points inside a function macro. But in a more general sense I'm not sure I would call this a "problem" unless you were intending to use the macro as a debug-symbol, and/or set debugging break-points inside your macro. Otherwise the macro is doing its job.

Jason
  • 31,834
  • 7
  • 59
  • 78
  • okay.. But how is that a problem.. It solved the purpose right, where i needed 1.653? – bruceparker Jan 12 '12 at 04:46
  • Yes, it solved its purpose. Basically the "problem" is that `ASPECT_RATIO` will not be seen as a symbol by the compiler, thus in a debugger, etc., you can't query the value `ASPECT_RATIO` as-if it were a variable. It's not a value that will have a memory address like a `static const int` may have (I say "may", because an optimizing compiler may decide to act like the pre-processor, and optimize-out the need for an explicit memory address to store the constant value, instead simply substituting the literal value where-ever it appears in the code). But I'm not sure I would call this a "problem". – Jason Jan 12 '12 at 04:51
  • I got your point EXACTLY Jason. Thanks. I just edited my question and that part of question has been answer by you now. Thanks. – bruceparker Jan 12 '12 at 04:55
  • BTW, try not to get confused between pre-processing a code-file and the act of compilation itself ... they are two different things. Pre-processing is kind of like using "find and replace" in a word-processor, except in a "smarter" way. Also once the pre-processor is done, it strips out all its directives since those directives are *not* C/C++ code. – Jason Jan 12 '12 at 04:58
  • Thanks Jason for advice. I got it.If you could copy paste your 1st comment in your answer, i could give it a tick mark. – bruceparker Jan 12 '12 at 05:02
  • Okay, I've edited my original answer with the content from my first comment. – Jason Jan 12 '12 at 13:35