Thursday, November 12, 2009

Be careful when you have to handle \0 character

I need to write some code to determine if a character belongs to a custom set. The code is as below:


bool isInMyCharSet(char ch)
{
const char* myCharSet="ABCD12349";
return strchr(myCharSet, ch)!=NULL?
}


The code works for years. Only one day you call this function with '\0'. Char 0 is not part of myCharSet, yet this function returns true.

Senior C programmers often know this, because this behavior is documented.


const char * strchr ( const char * str, int character );
char * strchr ( char * str, int character );

Locate first occurrence of character in string
Returns a pointer to the first occurrence of character in the C string str.

The terminating null-character is considered part of the C string. Therefore, it can also be located to retrieve a pointer to the end of a string.


OK. Fine, but do you know the same behavior exists in CString::Find method. This time, you won't find it mentioned in the document.

Now you may attempt to change the code to


for(int i=0; i if (myCharSet[i]==ch) return true;
}
return false;


Wrong again. sizeof operator still counts the terminating NUL character.


Tuesday, August 4, 2009

Unnamed namespace vs. static keyword

Language: C++

An unnamed namespace definition behaves as if it were replaced by


namespace unique { }
using namespace unique;
namespace unique {namespace-body}


The `unique' name here is guarranteed to be unique, among all translation units. You can put virtual anything into an unamed namespace, and they are exposed to the current module only.

You can also forward declare a function, and later define it, like this:


namespace { int f(int); }

namespace { int f(int a) { /* definition here */ }


And the standard proceeds to claim (paragraph 7.3.1.1.2)


The use of static keyword is deprecated when declaring objects in a namespace scope; the unnamed namespace provides a superior alternative.


Unfortunately I did not see things in this way. namespace is a great feature, however, static is quite obvious. Consider:


static int helper1(int, int, int);

...



This is quite straightforward, and takes less space. In a unnamed namespace, you need two additional lines, and the whole block is not clear to the first reader.

Yes static can't apply on enum and types. That is true. But since unnamed namespace always resides in a .cpp file, not .h file, what is the use of this feature?

Somehow I believe that the standard committee has overstepped on this issue. The statement should not be in the standard as it is more like a personal opinion.

Tuesday, March 3, 2009

Pecularities in Microsoft's RGB format

If you only worked in Microsoft platform, you are familiar with RGB color routines provided by Windows GDI. A COLORREF stores RGB value, and it is a 32-bit integer. Macro RGB is used to combine the three components into a RGB value. In order to get individual component values, you are provided GetRValue, GetGValue and GetBValue functions.

You may take granted that RGB value is stored as follows:

struct RGBValue
{
char reserved;
char RValue;
char GValue;
char BVaue;
};

and write code as below to print a color value:

printf("#%06x", color);

Until you are surprised to find that a red color is shown as blue on the screen.

Reason: Microsoft choosed to store R value at the last byte.

Sunday, February 22, 2009

Building QT4 static library in VC8.0

The QT open source since 4.4 provides builds for Visual C++. Unfortunately the default VC compiler flag is -MD (or -MDd for debug build), which means that the C runtime library is dynmically linked - which also means that you have to carry the MSCRT.DLL everywhere). It is not desirable for our project settings.

I did some research and found a utility called coolbuilder. It can build static lib. However, it proves to be a sh*t, as it failed to build. Worse, it sends out information without my permission.

Thursday, January 29, 2009

Tricky C code

We have a static library project linked into a DLL. For years, this static library does not require initialization/unitialization code. This time a new feature is added that requires the initialization and cleanup. So we have to call functions when the DLL is attached/detached to the process.

The original DLL does not have a DllMain. We got one by having VC++ create for us, and it did. We did this by creating a new DLL project and copy the function into ours:


BOOL APIENTRY DllMain( HMODULE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved)
{
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
case DLL_THREAD_ATTACH:
case DLL_THREAD_DETACH:
case DLL_PROCESS_DETACH:
}
return TRUE;
}


It was easy to paste code. Now we invoke functions:


case DLL_PROCESS_ATTACH:
InitMyLib();
break;
case DLL_THREAD_ATTACH:
case DLL_THREAD_DETACH:
case DLL_PROCESS_DETACH:
TerminateMyLib();
break;



Unfortunately did not work as we expected. Does anyone see the problem?

Saturday, August 30, 2008

Polymorphism in C

Many people mistakenly believe that polymorph ism has to be done in a OO language, such as C++.
Where it is true that C++ gives a quite straightforward implement, one might be shocked to find out that procedure language may have some advantages.

The techniques are not newly invented. It has been existed for more than a decade. For example, in Windows GDI, a DC represents a output device.

Tuesday, March 18, 2008

std::iostream adaptor for com::IStream interface

I am working on a C++ library that uses std::iostream for all kinds of IO. Now I finished it and started to add a COM wrapper above it. One of the issues is to convert IStream into std::istream. At the first glance, it is not easy since istream has a dozen methods.