Indexes, limits, bounds, etc., are always security-related with C code because of overflow exploit issues. Specifically, if you get the number wrong, you code is a candidate for exploitation.
Assigning the constant to a symbol does two things: it makes the number easier to verify in a review because it's immediately obvious what the number means, and more importantly, it ensures that every time you use the number in your code, you're using the SAME value.
Imagine, for example, where the number represents the length of the input field, and at some point you increase that length to accommodate larger names. If you've specified the value numerically in your code, you have to go track down every instance of that number and replace it, but only if the instance of that number represents your specific field (you can't just use search and replace to change every instance of 128 to 256 because the number could mean different things).
Furthermore, in some instances you may be using N+1 (e.g. to allow for termination), so you'd have to track down every instance of 128 and every instance of 129. And was there a reason to specify 130 as well? Oh, now it's difficult to remember. But don't miss any of them of you'll create a classic buffer overflow exploit.
If instead you just did #define FIRST_NAME_LENGTH 128
in one of your include files, and keyed all the corresponding values off that, then you can just change the number once and be done with it.
This is true even in instances where you only use the number once, because while you're CURRENTLY only using the number once, someone may need to extend the code in the future.
This is such an important issue that you should have been taught from day 1 to avoid "magic numbers" in your code. If the number "means" something, then you should make its meaning explicit.
Best Answer
Today, the preprocessing is actually happening inside the compiler (e.g. inside the
cc1plus
executable started byg++
command). Useg++ -C -E
to get the preprocessed form.Preprocessing and parsing is a well known art, and does not take that much time. However, the standard headers of C++11 (e.g.
<vector>
or<map>
) are pushing a lot of stuff. For example,#include <vector>
is pushing about ten thousand lines of code on GCC/Linux with GCC 5. This is one of the reasons why compiling C++ code is slow (another reason is that C++ being incredibly context sensitive, parsing it is slow: overloaded functions, naming ambiguity, etc...).Having many thousands of almost unused
#define
-d macros is not an issue today. (perhaps having millions of#define
might be an issue; I leave you to try that) Look into the source code of GTK or of the Linux kernel for some example.The reason it is not a real issue today (on current laptops & desktops, with e.g. 8GBytes of RAM) is that it is mostly filling some symbol table, and these tables can routinely handle many hundred thousands symbols.
Notice that optimizing compilers take lots of time in optimization. And C++ code practically needs to be optimized (in particular, because it has lots of trivial inlinable member functions, notably in template instantiation for standard containers, etc...). Even C code needs to be optimized (because current superscalar out-of-order multicore pipelined processors are really different from the processors of the previous century for which C have been designed).
If you are curious about where the GCC compiler is spending its CPU time (see also this question) pass
-freport-time
tog++
(and also-Wall -O2
for example). If you are even more curious, customize your GCC compiler with MELT (but that requires understanding something about GCC internals, which takes weeks).Notice that C (not C++) compilation is "fast" for its preprocessing & parsing phases (the bulk of the CPU time happens in optimization passes; experimentally, with
gcc -O2
, the compilation time is proportional to the square of the "size" of the largest compiled function). If you don't care about optimized code you could even try the tinycc compiler (which compiles about ten times faster than GCC or Clang, but produces slow machine code).