Some explanation on the windows API is needed here: Microsoft was very early introducing Unicode. Back then, they decided to represent a Unicode character in 16 bits. I guess this was a valid decision at that time. A wchar_t
on a Microsoft platform therefore is 16 bits wide, (Unicode) text is stored in wchar_t
s -- this had the advantage that every character had equal width. The drawback is that existing APIs, dealing with char
, weren't compatible any more.
Nowadays, with 32bit Unicode codepoints, this looks silly -- Unicode text on Microsoft platforms is encoded using UTF-16, so you have both drawbacks: not being compatible with simple char
-based strings and multi-character sequences. On many other platforms, wchar_t
is 32 bits wide and Unicode is either stored in these wchar_t
s or encoded as UTF-8 in "normal" char
s.
But back to the Microsoft API: In order to solve the problem, they renamed all API calls dealing with strings to have an A
suffixed and introduced a second set of the same calls, taking wchar_t
, suffixed with W
for the Unicode variant. Depending on a compile-time switch UNICODE
, the original names are mapped to the real names with either suffix by the preprocessor.
As you probably know, string literals in C have the type char *
. To make a string literal of type wchar_t *
, you need to prefix it with an L
. In order to automatically do this when UNICODE
is set, another macro is provided: _T()
. So what you are expected to do in your code is to wrap any string literal in _T()
, it will become prefixed with L
exactly when UNICODE
is defined.
Therefore, this line:
hComm = CreateFileA((LPCSTR)"COM8"
should instead read:
hComm = CreateFile(_T("COM8")
A word on LPCSTR
and LPWCSTR
: They are nowadays equivalent to just char *
and wchar_t *
. So casting is unnecessary. The reason for these names is backwards compatibility to ancient systems with segmented memory and "far pointers". As long as you don't need your code to compile for win16, just forget about them.
Finally a personal opinion: Windows knows Unicode for quite a long time (IIRC already with Win95) and it's standard nowadays. It's unlikely you ever want to target a windows system that doesn't support unicode. It's much more likely you want to write some portable code and then the problem is the different handling of Unicode (wchar_t
on Windows, char
with UTF-8 on most other systems, UTF-8 is also predominant on the Internet).
To help with that, I prefer to always define UNICODE
, use wchar_t
string literals for any constant string needed by the windows API (like your CreateFile()
call, so just prefix it with L
) and store all strings internally in char
using UTF-8, only converting them when you need to pass them to the Windows API. There are two functions for doing the conversion: MultiByteToWideChar()
and WideCharToMultiByte()
. That way, you can easily write adapters for the APIs of other OS's that use UTF-8.