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.
Dear Dr. Plauger,
I can program well in C, but I always worry about programming style and program portability. If clint complains about anything, however minor, I have to solve the problem.
Each time it complains, I remember that I probably would write my best programs in Ada or in Eiffel. Please tell me your opinion of those languages. I would love to keep writing in C. Sadly, my perfectionism make C programming a frustrating chore.
Thank you helping me.
Best wishes,
Bill McEnany
Your problem is perfectionism, not choice of programming languages. My approach is to develop a set of style rules, irrespective of what any compiler or lint tells me it likes, then exercise my obsessiveness in enforcing those rules. C works fine for me, under those circumstances. pjp
Dear CUJ,
I am not sure how to describe this concept but it seems similar to pure virtual functions. I want a base class that understands how to process a particular type of member variable but doesn't know how many there are until the user instantiates a derived class. So how about something called a "pure virtual member variable," e.g.
class CWidget { . . . // process MyTable algorithm 1 public void func1 (void); // process MyTable algorithm 2 public void func2 (void); private sometype MyTable []=0; }; class CMyWidget { . . . sometype MyTable [12]; };This doesn't compile because "pure virtual" is limited to member functions, but is there a concept that I can use to get the same results? Templates are all I can think of but that seems overkill.
Did this concept ever come up in the review process? Any reasons why this is not a viable design concept?
Thanks,
Gregg Teehan
gteehan@usa.netTemplates are hardly overkill, given what you're trying to do. Why not use a mechanism that's proven and does more or less what you want? And no, I don't recall any discussion of pure virtual member objects, or anything similar, during standardization. But then, I didn't attend all the subgroup meetings. pjp
Dear Marc,
I read your Editor's Forum from the June '98 issue of CUJ. Sad, but true, test engineers, are not respected. In my first job between my junior and senior years of college, I tested control software for a gas pipeline. I loved it. I found it a challenge to try to break someone's code.
After I got my first full-time job (at the same place), I found out that testers were known as the scum of the earth. I think I was the only developer who liked people in my test group. I found it a challenge to write code that would challenge the testers to find a bug. Anyone can find a bug in buggy software. I wanted the testers to roll up their sleeves to find bugs in my software.
One tester had an "attitude." He liked to find bugs. He rubbed it in when he found a bug. To most developers, this rubbed them the wrong way. When he found a bug in my code, he tried to rub it in, but I was too excited that he found a bug, and I wanted to know what it was. After he explained the bug, I congratulated him and thanked him! His attitude did change a little (more friendly), but that was not my purpose. I knew that he and I were on the same side to eliminate as many bugs as possible before ship date!
Seven years later, I switched jobs, again working as a developer. The test engineer needed help with a test program that simulated data communications to our "unit under test" (a medical instrument). The software project engineer told me not to help this person, because "he's the enemy." I totally ignored his statement, because I knew that any bugs found in the field and not found during the beta test cycle would be a thousand times worse.
I have also seen developers get very defensive when bugs are found in their code. They can get nasty! Why can't we all get along? I have always had a good attitude towards testing and towards being tested.
Here are a few points to ponder:
1. I tell other developers, "It could be worse, we could have to test our own code." When I ask them point blank at Beta 1, "Can we ship this to customers right now?" all developers tell me "No way!" Then I add, "Thank God we have the test team to test the software and help determine our confidence in the product."
2. I have no respect for developers who do not test their own code. I have very little respect for developers who think it is not their responsibility to make their software as bug free as possible. When someone says, "That's why we have the test team," they have just gone down a couple notches on my scale.
3. A little healthy competition never hurt anyone, but gains a lot. Mutual respect is critical.
4. Every "programmer" should start work as a test engineer / software reliability / software quality-assurance person. This way they can gain respect for what testers do. And whoever said testers can't (or shouldn't) program has never had to do regression testing!
5. Remember one thing, a developer and a tester have the same goal, to ship a product with as few bugs as possible.
Regards,
Mark Franjione
Senior Software Engineer
Host Engineering, Inc.Thanks for writing. Your passionate letter may just raise a few hackles. For example, I wonder how other programmers feel about #4. It might be a good idea for training purposes, but it probably wouldn't make the employment recruiter's job any easier. Testing is not what I would call a glamorous occupation. mb
Dear Editor,
I just ran across a problem with VC++ 5.0 and would like to find out if this is a bug in the compiler or if I am missing something:
The question is what should happen when a default operator is used for an argument of the std::string type. the following example code illustrates the problem I had:
// someheader.h: class AClass { public: AClass(int anArg, std::string aString = ""); // 1 // More declarations }; // End of file. // someheader.cpp: void AFunction() { AClass aClass(7); // 2 } // End of file.Line #1 doesn't cause a problem for the compiler. However, the compiler spits out the following error at location #2: "fatal error C1001 : INTERNAL COMPILER ERROR."
I believe this code should compile with no problems. If you can shed some light on this I would appreciate it.
Thanks,
Randy Astle
An internal compiler error is never excusable. All you can do is a) report the problem to Microsoft and b) find a workaround. My inclination would be to replace the single member function with two overloads, one with a single argument and one with two arguments. pjp
Dear PJ,
I read the article named "Using Shared Libraries Across Platforms" (Hong Xiao and Amal Shah, CUJ, May 1998) and notice that you incorrectly state that Win32 requires a .def file or a preprocessor directive in order to export a function (or data). __declspec(dllexport) replaces the __export storage class specifier available in Win16 and emits a linker option (#pragma comment(linker, "-export: <something>")). You can use DUMPBIN, a utility shipped with MSVC, with a /DIRECTIVE option on any .obj files to verify this. The complete syntax for export is:
/EXPORT:entryname[=internalname] [,@ordinal[,NONAME]][,DATA]Due to the calling convention, you have to figure out the name of the decorated function. However in many situations it's quite simple and more convenient when callers do not fully support decorated names (like VB).
Since you can replace declspec(dllexport) with a preprocessor directive when needed, you should always use __declspec(dllimport) because it produces optimized code.
I found your aticle very interesting and helpful. Thank you.
Sincerely.
Pascal Soveaux
Dear Mr. Plauger:
I was just reading your article on "The Facet money_put," and I have one comment on the code's readability. I have been programming in C++ for about seven years, and I do like the language, but I tend to stay away from the more obscure features. I use templates but have tended to stay away from iostreams. Your example here combines both ... but it seems to make the code very unreadable (looks worse than assembly!). It's code like this that makes the Java language much more appealing than C++. Do you agree?
Bill Walker
Software EngineerIostreams is much easier to use than to write. The same is often true for templates in general. The readability of this particular code is further compromised in several ways. First, the C++ Standard mandates the use of a number of advanced, and tricky, constructs. Its limitations on the use of names by library implementors dictates the use of all those underscores and capital letters. I'll claim responsibility for using short names and a generally cramped layout with next to no comments, but mostly the code just plain takes work to understand.
Pete Becker and I are currently writing our own version of the Java standard packages java.lang, java.io, and java.util. It is proving easier than C++ to write, and to read, in some ways. But the basic library is, by its very nature, chock full of tricks and special constructs. Java gets good marks for readability primarily because it is a far less ambitious language than C++. In the end, however, that just means that you can do less with it. We still have to write all the really hard stuff in C. pjp
Dear pjp,
I've been wondering what's that numpunct::grouping you're talking about. Then I concluded that you purposely coded num_get::_Getifld as you did to check if anyone is reading the code you publish. Therefore I write this feedback.
My guess is that the value should be something like {3, 3, 3, CHAR_MAX, 0}, in order to, say, allow for 10,000,000, and omit any check for longer numbers. Is that correct?
Unfortunately, Levi-Strauss didn't have the C++ Standard ready when he described the logical substructure underlying human behaviour in the various countries he visited. But we may probably carry on without knowing if any people will ever use those features.
However, the loop expression
for (const char *_Pg = _Gr.c_str(); _Sd && 0 < _I; --_I)looks wrong, as _I is already decremented in the body:
if (0 < --_I && *_Pg != _Grin[_I] ...In addition, the last condition of the previous loop (same function) features a call written as
_Grin.append((typename _Mystr::size_type)1, '\0')which also looks wrong, since _Mystr was typedefed after user's type _E whilst _Grin is just a string. BTW, I guess those casts are meant to avoid unexpected overloads. Would it be syntactically correct and/or computationally equivalent to code such as
_Grin.append<typename _Mystr::size_type, typename _Mystr::char_type>(1, '\0')?No, I'm not criticizing your coding style. I read a few complains about it, but I think your style is the next innovative thing I saw after Almond's. It is very skewed toward code publishing, but compactness may increase readability by reducing distractions. Of course, some code is not easily understandable and getting one's style blamed for that is the price for being innovative.
Regards
Alessandro Vesely
You did indeed unearth a problem with _I being double decremented. The type cast is also incorrect, however benign in this case. I find it necessary to use lots of casts with the library templates, since it is so easy to get a surprising template parameter match if you force the compiler to guess much. The notation that you show for calling template functions is indeed unambiguous, but is sufficiently new that I avoid it. Only a few compilers handle it at all well.I appreciate your finding and reporting these bugs. The down side of having code so widely disemminated is that all its shortcomings are aired in public. The up side is that the code gets steadily better, thanks to bug reports from many quarters. pjp
Hi,
Since my subscription expired and I'm not going to renew it, I thought that you might want to know why I'll stop reading CUJ.
First of all, it was getting less and less interesting for me. Since I started working with C, I've more or less learned about all the topics that interest me and that CUJ covers. In the last eighteen months, I hardly ever found anything new and interesting for me in CUJ.
This is probably something that happens with lots of magazines devoted to a single language. However, there are other issues that bothered me during the whole time I read CUJ.
One of them is the apparently missing concern for portability. I'm coming from the Unix world, and for me, portability was always a main goal in software development. Not so for CUJ. Many of the listings include DOS- or Windows-specific headers, use non-standard I/O-functions, rely on byte ordering and on the fact that an int is 16 bits (or is it 32 now?). Ignoring these issues means ignoring portability, and that is going to bite everyone eventually.
It may be that this lack of interest for portability is due to a certain bias towards DOS and Windows in general. I found it quite disappointing that CUJ never really tried to keep up with Linux, for example. Yes, there was an article (or even a whole magazine?) on it about two years ago. At that time, everybody had already covered the topic, and as far as I remember, CUJ did not do a very good job writing about Linux.
Finally, I was missing reviews. Everybody has to use tools for programming. A magazine devoted to one language (two now) should test and compare editors, debuggers, IDEs, documentation tools, etc. regularly. Very few people can actually afford to buy all the stuff only for testing purposes. I know that in the U.S., many companies offer a money back guarantee for software, too. However, this is rather rare in Europe, so at least your European readers might be interested in reviews.
Kind regards,
Christian Kirsch
Hi Christian,
We're sorry to see you go. The one criticism that stings a little (because it's true) is that we've not covered Linux very well. For some reason we've had a tough time getting those Linux programmers (actually, Unix programmers in general) to write articles. Could be they're just having too much fun working with an operating system that doesn't fight them every step of the way, like some OSs I know.
I cannot, however, let your comments go unchallenged to the effect that CUJ doesn't care about portability. Read any one of our columnists, and you'll find a person very much concerned about portability, not to mention abstraction, usage, style, and other issues related to sound programming. If our columnists don't explicitly mention portability every month, it's only because the notion is implicit in everything they write. I could cite half a dozen feature articles in the past couple issues that provided portable solutions. We aren't idealists, though. We will publish non-portable solutions if we feel they are of sufficient interest. Portability is important, but not paramount.
With respect to Windows, there are two aspects to portability: use of system-specific APIs, which cannot be avoided (hence the inclusion of your hated Windows headers); and non-portable thinking, which can and should be avoided. (An example of the latter is assuming an int is always 16 bits.) We try to avoid articles that reveal non-portable thinking, but Windows makes this difficult, because it practically forces programmers to be careless about portability. Windows programmers traffic in toxic substances like DWORDs and wparams, and unless they start with a cross-platform framework, they won't have to worry about porting to other platforms it probably won't happen. Yes, we do run a lot of Windows articles, but then, over half our readers are Windows programmers. If over half our readers were Linux programmers, we'd run lots of Linux, and I'll bet you wouldn't complain.
Finally, it would be nice to have product reviews such as you mention in CUJ. But a Byte magazine we ain't. (Come to think of it, neither is Byte these days. Hmmm...)
You've actually stirred up quite a few ideas in my head, especially regarding Linux. I wish you luck and hours of enjoyment with your next programming magazine. mb
Correction
Alex Bykov writes:
Marc,
I found a mistake in the article entitled: "Using Shared Libraries across Platform" in the May 1998 issue of C/C++ Users Journal.
Refer to the table on page 24, Table Entry 15 (Entry Point), Column entitled: AIX
The cell entry contains the symbol XXXX, meaning that AIX does not the appropriate option. However, the appropriate option exists and it is: eLabel So, XXXX should be replaced with eLabel.
Alex Boykov
Thanks. mb o