Departments


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.


Dear CUJ,

I have attached a re-worked MFC 5.0 version of W. Ward's program that transforms data using his Stream Encryption method into C strings [see "Applying Stream Encryption," CUJ, September 1998]. Null bytes are not embedded in the output by the engine. The rework was also necessary because I was unable to use the std::string class provided with the Microsoft implementation (it's still broken.) So I converted all the original std::string operations to use the MFC CString class instead.

The two files of real interest are ARACrypt.cpp and ARACrypt.h. The remainder make up a small test windows application to demonstrate the method. A compiled version of the demo program can be found in . .\release\TCrypto.exe. It has been tested under Windows NT 4.0 SP3 and should work fine with the current versions of Win95/98.

The changes I made may make Mr. Ward's work more useful to the "serfs" amongst us who need encryption results that must be operated upon by traditional C string functions or by the MS CString class, e.g. SetWindowText and the like.

Unfortunately, I was unable to locate Mr. Ward's contact information so that I could thank him personally or send this material on to him directly. If you would be so kind, please do so. Of course you and Mr. Ward are most welcome to use the enclosed programs, etc. in any way you see fit.

In advance, thank you.

Barnett E. Kurtz

p.s. I found the September 1998 issue to be very useful, informative, well written, and in short, terrific!

Thanks. We'll put your code on our ftp site with this month's posting. — mb


Letters to the Editor,

How many times has the suggestion to build a new version of C with bitfields as the fundamental type been made? I linked through to some of the standards web pages recently, and got an eyeful of C9X. I seriously wonder if it is possible to maintain so many keywords. Making bit fields the fundamental type seems to me a far more reasonable solution. We would probably need to give the new version a new name, something like "bit-C." (But isn't that already taken?)

I believe the two classes of problems with supporting independent bit fields are that very few CPUs directly support addressing down to the bit, and that programmer-specified integral types will generally conflict with the CPU's integral types. Concerning the former, if we can build compilers capable of handling nonlinear address spaces as extreme as X86 segments, surely we can handle addressing down to the bit.

Concerning the latter, providing a standard header which fully declares the CPU's integral types seems to me the only real solution to the problems most of C9X is trying to address.

I acknowledge that, in addition to independent bit fields, we will need keywords to specify two types of field packing for structures, tight (no holes) and loose (compiler does what it likes). Also, we will need a mechanism to declare the byte order and a mechanism to query types.

(While I'm tinkering in the virtual universe in my head, how about extending the width of bit-fields to some queriable arbitrary maximum width? I can't imagine bit fields wider than 65,536 bits, but 256 seems useful for 32-bit CPUs.)

Of course, the conversion between a strictly specified bit field type and a loosely specified (CPU friendly) type requires some new syntax. The mechanism for declaring byte order might look something like the code shown in Listing 1.

I slipped in yet another suggestion here. Name spaces are great for allowing the programmer to hide from keywords he shouldn't need to know very much about. Using the above declarations would be straightforward:

#include <byteOrd.h>
/* ... */
#vocabulary functionXXXXSpace
/* ... */
#context ByteOrderSpace
invertInt64_t
worldWidePopulation = 12000000000;
#local

We can keep the CPU default types, but now we can find out what they are? One application for this is handling variable-width characters. I've had occasion to work with character typing and code-set conversion with shift-JIS, and having to declare my conversion tables as strings, just so I can verify my own code (most of it generated mechanically), is wasteful, not to mention a pain in the neck.

Another application would be reduction of the complexity of interfacing with external files, but that goes without saying, doesn't it?

Joel Rees
fujicom@fujicom.office.ne.jp

If you "improve" C too much, it stops looking like C anymore. I leave it to you to think of real-world examples. — pjp


Dear CUJ,

The following suggestions for additional Standard C functions are humbly submitted.

asm — C could become the preferred macro language for assembly.

getch — Keyboards with more then 48 keys could be used.

gotoxy, clreol, clrscr, dellin, inslin — CRTs could be connected to the standard output.

setpixel, getmouse — This is just a wish list, probably too much to ask.

I don't want to be a heavy, but competing languages will surely be invented if Standard C fails to pick these up. Rumor has it that one called "coffee" is in the mill.

Ken Roger
Renton, Washington

Boy, it must be Fix Standard C month. Anyone else have any suggestions? (And we'll keep an eye on the "coffee," thanks.) — mb


Dear William L. Crowe,

I have read both of your articles — "Inter-Object Messaging Using a SwitchBoard" [June 1998] and "Comparing C++ and Java: A Java SwitchBoard Implementation" [January 1999] — and have some input.

While your Java SwitchBoard class implementation is thread-safe, your C++ one is not.

In my company, we use the SwitchBoard pattern to handle communication between front and back ends of our Win32 product. Our product consists of two threads running within the same process. All interested parties within the front end subscribe to the backend_event subscription. We use a mutex mechanism to insure that our notify, subscribe, and unsubscribe methods are not accessed concurrently by several threads.

In general, it is not uncommon to devote a separate thread to a time-consuming task. Imagine the following scenario. A lengthy task with an associated progress dialog starts on a new thread and subscribes to a certain subscription. If this task completes its execution and calls _unsubscribe, and while it is executing it another thread calls _post, it can cause data corruption. The variable _hookups that holds SubscriberHookups can be modified concurrently by several threads. The consequences of this are truly unpredictable.

In Java, you use java.util.Vector to hold SubsriberHookups. All methods in this class are declared to be synchronized. The implementation of nextElement in VectorEnumerator also provides for the protection against the simultaneous access by several threads. What this means is that we can expect exactly two scenarios. In the first case, the exiting thread will receive the notification, process it, and then exit. In the second one, the exiting SubscriberHookup will be removed from the Vector, exit, and not get any notification. Either outcome is fine and preserves data integrity.

This once again, proves the point that Java's builtin support for multithreading and thread synchronization make it a desirable language for multithreaded applications.

Sincerely,

Ilya Tilevich
Information Builders Inc.

Ilya_Tilevich@ibi.com

William Crowe replies:

Your point about the Java SwitchBoard being thread safe out of the box would have made a nice addition to the Java/C++ SwitchBoard comparison. Java's threading model makes it extremely easy to write threaded applications, especially since most of the time you don't have to worry about mutexes — synchronized methods handle the bulk of the job quite well. It has been my experience with Java, however, that much planning, analysis, and design is still required in order to write effective multi-threaded applications, albeit less than in C++. Just because an application can be threaded doesn't necessarily mean that it will perform any better (as I am sure you already know). As you pointed out, the Java implementation of the resulting design is where the big payoff is realized, that being simplicity and time to market. A very nice alternative to multi-threading C++ indeed.

Thanks for the input,

Bill Crowe


Greetings,

I'd like to briefly discuss Chuck Allison's "Jumping into Java" column (CUJ, January 1999). Chuck refers to a missing equivalent of the C++ delete operator in Java. While it's true that there's no explicit delete, the closest one could hope to simulate a delete for object N is to write a short Java snippet that will remove a reference to a given object and call the system garbage-collection routine:

N=null;      // free up object N was referring to
System.gc(); // call garbage-collect

Please note that explicitly calling System.gc() doesn't necessarily force a collect to occur. The Java runtime system will still wait to collect until it's damn good and ready.

Chuck states that Java has no destructors. This is not true. The protected finalize method is a destructor. finalize (when implemented for a given class) is called just before the garbage collector attempts to dispose of the object. Please consider the following Java application:

// Dummy.java
public class Dummy {
   public static void
   main(String[] args) {
      jimbo j;
      for(int i=0;i<1000000;i++) {
         j=new jimbo();
         System.out.println
            ("Iteration " + i);
      }
   }
}
class jimbo {
   protected void finalize() {
      System.out.println
         ("Going out of scope!");
   }
}

The application continuously creates new instances of the class jimbo. As you watch the iteration counter increment, you'll eventually see the text "Going out of scope!" appear on the screen. This messages is generated when the finalize destructor method is called.

I'd like to note that the above example displays a String and an int on the output console even though no printf equivalent exists in Java.

I find that since Java treats String objects as first-class citizens rather than arrays of characters, automatic conversion of other types to Strings can be much more handy when formatting data. Granted, this is the kick-off column in the series. I hope that Chuck visits the subject of String objects in Java in great depth.

A particular fascination of mine is that all String literals are actually valid String objects. (Try to evaluate the int expression ("Hi there").length() in a snippet of Java code. The value should be 8.)

I also hope that a discussion on simulating multiple inheritance by using Java interfaces is also in the works for future columns.

Chuck Allison replies:

I am aware of System.gc and finalize. Since you have no practical control over when objects are really collected, and because of the two-phase action of the collect/finalize cycle, there is no equivalent in Java of C++ destructors. finalize is not useful for deallocating resources — such as files, DBs, etc. — in a timely fashion.

Since one usually wants to have more fine-grained control over such things, finalize isn't good enough. I don't know any seasoned Java developers who use it. Perhaps this is because it never really worked correctly until recent versions. Also, there is no guarantee in Java that all objects that conceivably could be collected will be. This is the key reason for my comments. Please see pages 162-163 in Bruce Eckel's Thinking in Java. He explains it very well, and emphasizes the point that "Garbage collection is not destruction." Here's a personal email I recently received from Bruce Eckel about finalize:

"The problem is that the finalize mechanism is broken, and has never worked correctly. I don't know if it ever will, but I've written it off completely. One of the places you discover that finalize is broken is precisely in closing files."

As for Java I/O, it is true that in Java you can display Strings and ints on the output console with System.out.println, but no formatting is available this way. To get formatting, you have to use the formatting classes in java.text, which is much more complicated than using printf.

Finally, note that the C++ string class is also first class. Character arrays are discouraged in C++. I will certainly look at strings in depth in future installments of my column. I will also discuss multiple inheritance, as well as the importance of interfaces in their own right. (I am assuming you don't mean multiple implementation inheritance. That is not supported in Java.)

Thanks for writing.

Chuck Allison
cda@freshsources.com


Dear CUJ,

I read C/C++ Users Journal from cover to cover just as soon as it arrives, and I get many good ideas, and ideas to incorporate into, or change, in my existing code. One thing puzzles me however. Many of the letters to your magazine begin, "I am writing this code and I have a Problem/Question/etc."

Now, whenever I am in that situation, the answer is normally required yesterday and I need to find it immediately, so how can these guys wait for the reply to be printed in your magazine?

Bryan Anslow
Thousand Oaks, CA

Ever hear of a blocking thread? Just kidding. When it's a technical question we often send the answer back right away, via the miracle of email. We repeat the question and answer here for illustrative purposes. — mb


Dear CUJ,

in a letter to the editor in the January 1999 issue of C/C++ Users Journal, Michael Eager states that the C and C++ standards do not require compilers to follow the evaluation order of expressions as specified by parentheses — and you thanked him for pointing this out. But the ANSI C standard, at least, explicitly revoked the license of compilers to reorder expressions, "... thus bringing C into accord with most other major high-level languages" (cf Rationale for the ANSI C programming Language, section 3.3).

Keith Wilkinson
Optimay GmbH
keith.wilkinson@optimay.com

The C Standard makes unambiguous how terms group in an expression. Parentheses can change the grouping, but are not needed to make grouping unambiguous. The order in which operators (including function calls) are evaluated, however, is a different matter. Evaluation of subexpressions can even be interlaced, if no sequence points intervene. It's a subtle point that's quite often overlooked, and thus remains the source of subtle portability bugs in both C and C++. — pjp o