C/C++ Contributing Editors


We Have Mail


Letters to the editor may be sent via email to cujed@mfi.com, or via the postal service to Letters to the Editor, C/C++ Users Journal, 1601 W. 23rd St., Ste 200, Lawrence, KS 66046-2700.


Correction: In Etienne Richards' article, "Adding Level-2 Thread Safety to Existing Objects" (February 1999, p. 61), an erroneous statement was made about the manner in which threads are activated. The correct statement is: "If there are multiple threads performing a wait they will be queued according to the operating system strategy." (The article text on page 61 used the word "signal" instead of "wait.") We apologize for any confusion this may have caused. — mb


Dear CUJ,

You probably have already received feedback, but just in case:

Chuck Allison's "Using Primitive Types and Wrappers" (CUJ, March 1999) has an error in his description of operators and short-circuit evaluation. He statues that "For example, if i is less than N in the following expression, then a[i] is not even evaluated:

if (i < N && a[i] != 0)

I would guess that he meant the expression to be:

if (i < N || a[i] != 0)

or, perhaps he meant:

if (i > N && a[i] != 0)

At any rate, his is incorrect because of course with i being less than N, i < N is true, and a[i] != 0 must be evaluated to resolve the logical and.

While I'm here — I too subscribed to the C Users Journal, now the C/C++ Users Journal, primarily to follow C/C++. However, I program in other languages, so anytime that you include information on those other languages (Java being the recent diversion), especially when it is related to C/C++, I welcome it! Keep up the good work.

G.Durham
gdurha1@erols.com

That Chuck Allison. He's such an honest guy that when he makes a simple mistake no one here catches it. I believe he meant to say "if i is greater than or equal to N in the following expression, then a[i] is not even evaluated:"

if (i < N && a[i] != 0)

which would make a lot of sense if a were an array of size N.

I'm glad you enjoy the Java coverage. But we'll make sure to keep it related to C/C++. Thanks for writing. — mb


Mr. Plauger,

I'll get straight to the point.

Why go through the effort of making an embedded C++ when one can simply mimic objects in C?

I was once an avid C++ follower, spending many hours learning the language as best I could. However, the more I understood it the more complicated it became. At the end of it all, I was disenchanted with C++'s usability due to its added complexity for anything but the largest of software systems.

I am a true believer in object-based programming. I'm a believer in encapsulation, interface inheritance, and polymorphic behavior. So why not just mimic these features in C and forget about embedded C++?

I'm sure your a very busy person and probably can't answer everyone's questions. But maybe you have already have written something about the justification of embedded C++ (or can in the future :). If so, where could I find it. Or maybe you could just forward it to me.

Thanks in advance for your time, and thanks again for the great articles in the C/C++ Users Journal.

Kurt Ottaway
Sr. Software Engineer
Identix Corp.

"Simply" is in the eye of the beholder. C++ performs stronger type checking than C. It also supplies nice notation for calling virtual functions, passing "this" pointers to member functions, and encapsulating member functions in a hierarchical name space. Embedded C++ retains all these demonstrably useful features while avoiding some of the more abstruse, and less efficient, features that have been piled onto C++ over the past several years.

On the other hand, I confess that I had to write a nontrivial program in C a year or two ago. (It was a Java to C translator.) I can't say that I missed much from C++. But then, I consider myself a pretty practiced and disciplined C programmer. C++ would still have been a better choice, were it not for some marketing considerations. — pjp


Dear CUJ,

I have recently read your article entitled "Using C++ with Word97 COM Interfaces," by Jim Langseth, in your January 1999 issue. In the article, Langseth mentions that significant documentation exists for manipulating Word with Visual Basic for Applications, and that "using C++ is a bit trickier."

I have come to the same conclusion as Langseth, and have found that it is much easier to write code that drives Word using VBA COM Objects, and then calling the VBA COM objects from C++ through custom interfaces.

One could convert Langseth's WordStream class to a COM interface as shown in Figure 1.

In Visual Basic the IWordStream interface could be implemented in a class module as shown in Figure 2.

Once the VB code is working, one can extract the CLSID for the VB COM object from the registry, or use the COM-Object viewer to get it. In C++ one simply has to create the object, get the interface, and use it.

static const CLSID
CLSID_WordStream = {....};
     
HRESULT DoReport()
{
   HRESULT hr;
   IWordStream* ws = 0;
   hr = CoCreateInstance(
           CLSID_WordStream,
           NULL,
           CLSCTX_ALL,
           IID_IWordStream,
           (void**)&ws );

   if (FAILED(hr)) {
      // handle failure
   }
   // do interesting things now...
   hr = ws->put_FontSize(10);
   if (FAILED(hr))
   { // do something }
     
   hr = ws->AddText("A Text String");
   if (FAILED(hr))
   { // do something }
     
   if (ws) {
      ws->Release();
      ws = 0;
   }
   // finished
}

As a final note, if CLSCTX_ALL is used for creation of the object, one can debug the VB code in the VB Debugger. Alternatively, one can compile the VB DLL with Codeview debug info.

I have found it much easier to drive Word, Excel, or whatever, using VB COM objects, simply because of the wealth of documentation available.

Craig Funk
PanTechnica Corporation
Eden Prairie, MN
cfunk@pantechnica.com

I never thought I'd see the day we printed so much VB code in CUJ, but you've given us a good reason. Thanks for presenting an interesting approach. — mb


Dear pjp,

I read with interest both your column on EC++ and the message by Rick Tillery, in the February issue. I'd like to thank both of you.

Personally, I often do switch on strings, as in:

for (i = 0;
   i < sizeof X/sizeof X[0]; ++i)
   if (strcmp(str, X[i].str) == 0)
   { treat_case(i); break; }

When I'm in a better mood, I define the X array in sorted order, either by hand or by invoking sort from the makefile, so that I can do:

char **r = (char**) bsearch(&str, X,
      sizeof X/sizeof X[0],
      sizeof X[0],
      my_compare_X_str);
if (r)
   treat_case(r - (char**)X);

where my_compare_X_str just dereferences its arguments and calls strcmp.

Yet another alternative is to use a C++ map, which requires heavier initialization.

I think Rick's idea, to switch on the first letter of the keyword, may be more efficient than using bsearch. However, it is much easier to generate an ordered array X than to generate the code that switches on the first letter.

In this respect, I deem Rick's argument as self-contradictory. Building a jump table based on the first letter (well, why not on the integer value that results taking the first four chars?) of each token, is exactly the kind of job that one would expect from a good optimizing compiler. Hence, his argument should only be mentioned by those who sustain the opposite thesis.

Then, lots of compilers degrade the switch statement into an if-else cascade. (Some are known to require the values to be spelled out in ascending order.) I would suggest that a programmer considers the compiler and the machine as a whole, where the lack of optimizations can be compensed by a faster processor. Programmers should be happy when they have written some clear code which can be maintained by humans and optimized by compilers.

Since processors are now so fast, most software buyers don't consider efficiency very important. Yet, efficiency is a good razor for discriminating language features. Your discussion on EC++ is much more enlightening than your answer to Rick. Or should I interpret the latter as a compressed version of the former?

I always dreamt that I wrote an algorithm to compute the first few digits of PI, without calling external functions except for the printf that finally displayed the result. Since the program took no input, it computed a fixed number of digits. I then compiled it and run it. And I was surprised to find out that the program executable was binary the same as the hello-world program

#include <stdio.h>
     
int main()
{
   printf("%s\n", "3.1415926536");
   return 0;
}

Thanks again for maintaining a balanced global vision of language evolution. (And I'm looking forward for your column on C9X.)

Regards

Alessandro Vesely

Yes, good compilers optimize switch statements aggressively. But sometimes it is the mark of a good programmer to write code that doesn't depend on a good compiler to run fast enough. The hard part is knowing whether your more elaborate code is really going to make a difference in the field. — pjp o