cprogrammer
cprogrammer

Reputation: 5675

Is preprocessor blindly replace the defines?

I have a class that has a member function called SendMessage. No member function named SendMessageA exists in the project. Project is multibite, so I have a define

#define SendMessage SendMessageA

If I call SendMessage somewhere in that class, will my project call SendMessage or SendMessageA ?

If the replace is made by preprocessor,the project should not compile. Right ?
But I see in a dump that SendMessageA is called ... end eip register is not in any VAD

EDIT

A more specific question: is preprocessor blindly replace the defines ? or first checks for a match in the class ?

Upvotes: 0

Views: 1377

Answers (4)

SigTerm
SigTerm

Reputation: 26439

How C++ preprocessor works

In case of #define A B preprocessor replaces ALL occurences of A with B. It is pure substitution.

Will my project call SendMessage or SendMessageA ?

Your project will call either SendMessageA or SendMessageW - depending on whether it was compiled with unicode support or not. There's no SendMessage function - it doesn't exist.

f the replace is made the project should not compile.

SendMessageA is declared within <widnows.h> (or in a header that is included from windows.h) - somewhere, and its linking info is within one of base system libraries (User32.lib, I think). If you're on windows, there's a very good chance <windows.h> is #included from somewhere, and corresponding *.lib is already in linker dependencies.

--EDIT--

A more specific question: is preprocessor blindly replace the defines ?

Yes, preprocessor blindly replaces defines. For non-blind replacement you have templates, but they have their own limitations. Some thing that can be done with preprocessor cannot be done with templates and vice versa. Preprocessor have stringize operator, templates have type-checking and metaprogramming.

My problem is why sometimes the member function SendMessage is called because the code works (most of the time)

If you have SendMessage method in your code (BAD idea on windows platform - clashes with system macro, replace with sendMessage() or use different name, because even namespaces won't help you to avoid omnipresent preprocessor) your method (not SendMessageA/SendMessageW) will be called from *.cpp ONLY if <windows.h> was not included in that *.cpp.

Compiler operates at one file at a time, and has no knowledge of thing that go on in other files, so if there's no <windows.h> #included, your method will be called, because preprocessor won't have any knowledge about SendMessage #define (from <windows.h>). If <windows.h> is included, then ALL occurences of SendMessage will be replaced with SendMessageA/SendMessageW, because preprocessor does its job first.

One possible solution in your situation would be to avoid using naming convention similar to the one in Win API. I.e. make sure that function names don't start with capital letter. That'll solve many problems, but you'll still get minor trouble from min/max macros.

Upvotes: 2

Mr Lister
Mr Lister

Reputation: 46599

In the Windows API, there are the two functions SendMessageA and SendMessageW. You will be calling one of these two, depending on what #defines you have in your program.
Are you sure that is not what happens?

Edit: oh wait. Is your #define SendMessage SendMessageA before the definition of the SendMessage member function in your source? If so, the compiler will simply use SendMessageA for the name of the member. Otherwise, your function will be SendMessage, but the rest of your program will call the built in Windows function SendMessageA.

If you have many source files, maybe some of them will know about the #define, while others won't.

My recommendation is to rename the member function to something else and dispense with the #define.

Upvotes: 1

s3rius
s3rius

Reputation: 1452

The Preprocessor runs through your code before compilation. So any SendMessage would be converted into a SendMessageA. The compiler will then look for a function called SendMessageA and call it.

Upvotes: 3

Šimon T&#243;th
Šimon T&#243;th

Reputation: 36451

The preprocessor works as a text macro processor. If a macro is defined, all occurrences of the macro are replaced with it's definition.

#define blabla some_real_stuff

struct blabla /* blabla will be replaced with some_real_stuff */
{
   void method();
};

int main()
{
   some_real_stuff x;
   x.method();
}

Upvotes: 2

Related Questions