Letters to the Editor + CVu Journal Vol 10, #6 - Sep 1998
Browse in : All > Journal Columns > LettersEditor
All > Journals > CVu > 106
Any of these categories - All of these categories

Note: when you create a new publication type, the articles module will automatically use the templates user-display-[publicationtype].xt and user-summary-[publicationtype].xt. If those templates do not exist when you try to preview or display a new article, you'll get this warning :-) Please place your own templates in themes/yourtheme/modules/articles . The templates will get the extension .xt there.

Title: You Write - The Editor Replies

Author: Administrator

Date: 07 September 1998 13:15:28 +01:00 or Mon, 07 September 1998 13:15:28 +01:00

Summary: 

Body: 

From Tony Houghton

Dear Francis After reading the Harpist's article on names I once again felt moved to make a few comments.

The first point is scope of some types of name. The Harpist considered enums and typedefs to have global scope, with enums possibly having file scope. In my opinion they both have file scope because there's nothing but common sense to prevent you from using the same name for two different types or values in two different files.

As for struct etc tags, you can't quite avoid using them altogether; they're needed for self-referencing structures such as linked lists. You never need to use any tag more than once (to give it a typedef), but wherever there's self reference you will have to use it that once.

He also said that

struct B {
  int data;
};
struct C {
  int data;
};

are both considered to be the same type in C. Not according to my compiler, it wouldn't allow one to be assigned to the other or one's address to be assigned to a pointer to the other type. I used Acorn/ARM Norcroft C, one of the strictest ANSI compilers around. If it were merely dubious, but legal C, I think the compiler would be required to produce only a warning, not the error that it does. I don't think his advice to avoid macros altogether is sound either.

Constants can be better served by using enums and small functions should arguably be kept as small functions, not macros, but there are some very cunning tricks that just aren't possible without macros. They're just about essential to avoiding problems caused by multiple inclusion:

#ifndef THIS_HEADER_H
#define THIS_HEADER_H
/* Body of header */
#endif /* !defined THIS_HEADER_H */

I usually make multiple builds from one source tree of my projects now with different levels of debugging, and being able to pass macros into the compiler from the makefile is a much more convenient way of controlling which type of debugging to use. I also use a macro called E (it's used a great deal so the less I have to type each usage the better, and I know I'm not using 'E' for anything else) around all my OS calls to check for a returned error condition with various levels of debugging. One of those levels of debugging incorporates __LINE__ and __FILE__ into the error message, impossible if E were a function.

I'll let him off the "DON'T even think about goto", but I've found that they can actually improve readability if used very carefully in certain switch statements where many cases share a few common instructions. I wouldn't ever think about jumping backwards though.

PS I decided to cheat with me tagline. I usually have one chosen at random from a small selection, but now seemed like a good time to force one of my favourites.

Tony Houghton

There's nothing like C for doing exactly what you didn't program

The Harpist's respons:

Unless there are very good reasons otherwise, I always try to give advice on programming style that will work equally well for C and C++.

In C++ there is no doubt that an enum is global unless it has been explicitly placed in some inner scope. Until the advent of namespace there was no way that you could provide a non-local enum that was not global. As far as I know, no one has ever proposed that enum should have internal linkage by static qualification of its declaration.

Now I grant you that a typedef has filescope visibility but Microsoft, in its wisdom, provide a mechanism that turns typedefs identifiers into true type names. Type names are used in name mangling in C++ and so become visible to the linker, in other words they have extern linkage. I know that this is not part of pure C or C++ but so many people use Microsoft development tools that you would be unwise to ignore this extension.

For compatibility I would always typedef any the tag with the same spelling. So If I was going to use tags (and actually, for C++ portability I should) then I should write:

struct myType {
/* declarations */
} myType ;

Though I wish that the rules of C and C++ did not leave me writing such things for portability. To typedef your structs to anything other than the tag seems silly to me.

On the subject of different tags for identical tags, I am guilty of eliding two thoughts. In C, you can use different tags in different files yet the layout rules guarantee that confusing them will not cause problems. This is another way of saying that tags do not have external linkage in C. You are of course right that the compiler can distinguish them. Thanks for correcting me.

Did I ever say that you should never use macros? If so I apologise. However I have a set of very strict requirements. Use them for header guards, nothing else works. But always end them with _H and never ever end any other identifier that way. If you must provide conditional compilation, then use a sensible all upper case preprocessor identifier. Use the built-in macros (they are there for use, so it would seem silly to remove them, anyway they are outside the users namespace as they start with a double underscore)

I suppose that if you do not have any form of configuration management that using macros the way you suggest to control levels of debug are acceptable. However the idea of using a single letter macro seems very suspect to me. You may never use them for anything else but modern code is written by extended teams.

You may use goto sensibly, and I know Francis is fond of pointing out that the Pascal goto is used by Donald Knuth in both TEX and METAFONT. Unfortunately it is too easy to abuse and most times what appears to be sensible use is just a symptom of a poor code style. I frequently see it recommended as being a good way of getting out of nested loops. However nested loops are often a symptom of flawed programming.

From Klitos Kyriacou

Hello Francis,

I am writing to ask about the ACCU's policies on advertising a job through C-Vu and/or the mailing list.

The team I'm working in has a vacancy at the moment for a technical consultant with good skills in (at least several of) C, C++, Java, Corba, COM, Object-Oriented Design (including things like OM/T, UML, Design Patterns), as well as having the right character (business-minded, assertive, etc.)

Recruitment agencies have sent us people who claimed to know C++ etc. As you can imagine, we have come across too many people who marketed themselves as C++ experts after reading bad books, like those by Schildt and Oualline. Sometimes, it was not entirely the candidate's fault, they mistakenly thought they knew C++ well.

I am more impressed by the obviously high average level of skills shown by ACCU members. However, asking on the mailing list would possibly be seen as commercial abuse of ACCU's facilities, even though I am a member. Could you tell me your policy on this.

Klitos Kyriacou

I am publishing this letter for two reasons. First one or two of you might be interested in the job possibility. If you are, email me and I will pass it on to Klitos who will be able to provide further information. I have not published Klitos' email address here because this letter was an informal one and should not involve his employer.

The second reason is to respond to his questions publicly for the benefit of all. ACCU does not allow invitations for employment to go out other than as an advert or letter in one of its publications. The contact details for many members are their employers. Quite understandably employers get very upset by having their employees canvassed for employment elsewhere. Of course direct adverts and published letters have to be acceptable (that is one way we raise money). Normally we charge for advertising jobs - not much by commercial standards but a charge none-the-less.

That candidates thought they had adequate skills but did not is the fault of the employment agency whose service to employers should include weeding out the under-qualified.

From Suradet Jitprapaikulsarn

Dear Francis Glassborow,

First of all, I have to apologise for contacting you in this manner. Your book reviews on ACCU has been a major sources of my reference. Apparently, I have to teach C++ to a group of high school students. Even though all of them have been exposed to computer in some certain degrees, some have no programming experiences. Could you recommend me a book that help me teach object-oriented concept from the beginning? I believe that object-oriented programming concept need to be incorporated from the beginning of learning C++.

Looking forward for you help.

Suradet Jitprapaikulsarn.

PS: Please forgive me for my poor English.

I have replied but I thought you might be interested and that some of you might like to offer advice.

From Chris Southern

Dear Francis

How very dispiriting for our editor. Every issue must be a struggle to get contributions, even letters. Yet the topic of money brings in a torrent.

Well I don't want to be left out! I just need to interrupt the paean in favour of agencies with a brief anecdote. I do not dispute the need for them nor that the cash flow service they provide is not essential.

I expected to be taken advantage of in my first contract. But… A few months after I started it was the beginning of a new calendar year, and one of the three agencies providing staff at the site told its people that the employer had upped the rate in its normal annual review. The contractors should therefore charge at a new rate from their next invoice. The telephone lines to the other two agencies were very busy in the hours following this revelation. One agency said that of course the rate would go up they just had not got round to it yet. The third said 'We pay our contractors what we believe they are worth, and review that after each year elapsed on a contract'. The employer was paying a flat rate to all agencies for all contractors. In my view that would entitle them to expect some minimum standard of contractor to be provided, not ones that the agency felt were not worth the money.

C Vu occasionally carries reviews of the SIGS Journals, e.g. C++ Report, JOOP, and I felt that a general observation might be appropriate. I believe that articles appearing have not been subjected to peer review in general. Some articles seem barely disguised advertising, although it is a fine distinction to draw between telling people how to get the best from your product and promotion of that product to non-users.

The last couple of issues of Java Report have been instructive. Obviously not all the Java developers are previous C++ developers. Issues are being raised which the C++ community is entitled to greet with 'been there, been bitten by that'. I was particularly taken with the sentence describing Java's habit of passing objects as non-const references: 'This gives the actual argument a bewildering mixture of value semantics and reference semantics.'.

Apparently not spotted as an issue was public derivation for implementation. The thread pool class seems a good concept, simultaneously speeding up launching a handler and preventing the massive drain on system resources that could result from indiscriminate spawning. But its type was 'ThreadPool extends java.util.Stack', and it overrode the pop method to start a handler, and the push method to wake any tasks that were waiting for a handler. The author even knew deep down that something was wrong, as the push method contained the comment 'Would like to assert theObject is a kind-of thread'.

Another article in the same issue was suggesting 'generic' interfaces, which turn out to be run-time lookup of field and method names in a class which would otherwise be a mostly 'getter/setter' one. This author believes that the type system is something to be evaded, rather than a 'hard but fair' guard against accidental misuse. I think I have been told that a class full of fields and get/set methods with one or two methods which calculate derived attributes is probably the wrong design. It probably comes under the category of random cohesion, to adapt a description from structured programming discipline.

Perhaps we can start a letter thread about technical issues.

Chris Southern

Now I am all in favour of that last paragraph.

I have not seen copies of Java Report so I cannot express a specific opinion but I certainly have the impression that those writing about Java frequently lack the kind of expertise and insights that exemplifies a good practitioner. I wonder if we can persuade Chris to contribute a regular report on one or two publications (particularly those aimed at the Java community.)

From Richard Blundell

Hi Francis,

I was just reading C-Vu 10-5, and thought I would send a few comments and/or ideas. A few articles referred to previous ones that rang no bells, and checking my shelf I couldn't find the last issue. It is possible that I have mislaid it, but now I come to think about it I am not sure I got one since March so I may have missed 10-4. I'll check my desk and let (you?) know if I am out of luck.

First, you mentioned the office assistant and removing it. I have installed Rocky the dog, and personally I quite like him. However, if you right click him, pick options, and reset all the check boxes such as "Show Tips..." and "Respond to F1 Help", you should find that, once hidden, he doesn't appear much more. You can also customise the toolbar and remove the assistant button. Finally, if all this fails, you could delete the .act files in the office/actors directory (in fact, to install a new assistant, all you need to do is copy the new .act file into this directory), and I think this should stop them appearing.

Rounding errors. The reason many calculators (and possibly VC, but I'm not certain about that one) get calculations such as 1.0 / 3.0 * 3.0 correct, plus many other floating point calculations, and give the impression that they are giving the infinite precision results, is that they effectively store an extra digit which is never displayed but is used solely to round answers. Thus if 1.0 / 3.0 gives 0.333(3) (let's pretend it only shows 3 d.p.) when multiplied by 3.0 again it gives something like 0.999(9), and the calculator uses the extra digit (shown in parentheses here) to round the result to display 1.000. It could be that VC++ uses a similar technique (or maybe uses a few extra bits rather than a whole base-10 digit). Alternatively it could be using 80-bit arithmetic in your PCs math coprocessor/FPU, and then rounding for your double result to 64-bits, using the excess 16-bits (or at least the excess that is part of the mantissa) for rounding.

Of course the more operations that are involved in a calculation, the larger and larger any total accumulated rounding error is likely to become, and at some point, the calculator's trick of using an extra digit will not be enough and the error will show up on the display. Perform even more calculations, and the error can become sizeable. In general, therefore, when comparing floating point numbers, I would always use a sig. figs. approach rather than a decimal places comparison, since you have no idea how big the numbers being compared are. If you want to compare two numbers up to, say, 5 decimal places, then that might be fine for numbers like your 1.414, but for numbers around a hundred you would be stretching the precision of a float. For much larger numbers you would have the same problem with doubles. Knowing the precision at which doubles are stored on a particular machine, however, allows you to find the number of significant digits that they will hold. Comparing numbers to a few fewer significant digits will then allow you test numbers of any magnitude for equality with much more safety.

Thus, if you wanted to compare two numbers to 10 sig figs (assuming your doubles held more than this) you could compute something as follows (note that I have just jotted this down, so there may be more elegant ways of doing it, and this might not actually give you the number of significant figures because of the way it calculates - it might be a fraction off in general. Disclaimer, disclaimer, disclaimer 8-):

bool compare_sig_figs(double lhs, 
                      double rhs, int sigfigs){
    // Calculate the required maximum difference
    double epsilon = pow(10, -sigfigs);
    // Find the absolute difference between them
    double diff = fabs(rhs - lhs);
    /* Compare the fractional difference to the
       required difference.(Should really check 
       we're not going to divide by zero here!) */
    return diff / ((fabs(rhs) + fabs(lhs)) / 2) 
                                          <= epsilon;
}

The reason I average the left and right hand sides is in case they are quite different and cross zero (e.g. comparing -0.00001 to 0.1 - the result would vary widely if only one or the other were used. You could alternatively use just the larger of the two numbers (ignoring sign)). Note that the above will produce undefined results when lhs == rhs == 0, and this case needs to be checked for.

Here are some results from the above:

100.2, 100.1 at 2sf gives true 100.2, 100.1 at 3sf gives true 100.2, 100.1 at 4sf gives false 123456789.123, 123456789.122 at 8sf gives true 123456789.123, 123456789.122 at 11sf gives true 123456789.123, 123456789.122 at 12sf gives false

My doubles hold 16 or 17 significant digits. As shown above, the function distinguishes between numbers of varying magnitudes as expected, and so using something like:

compare_sig_figs(a, b, 15)

would be a good way to test doubles for near-equality regardless of their magnitude.

Richard Blundell

Missing or Damaged Magazines

Any time you think that you have missed a copy of C Vu just call me or even better send me an email. I will then get you a replacement. Reasonable 'complaints' are always dealt with promptly and with, I hope, courtesy. I would always prefer that problems that require resupply were brought straight to me.

One member rang me at 9.30 one evening, lacked the consideration to check that I was not being inconvenienced (I do not mind calls in the evening but I should be given the opportunity to set another time.) and started complaining about materials damaged in the post. The main burden of his complaint was that, while the supply officer had replaced the first set of damaged periodicals he had declined to replace some more that had been damaged. If he addressed another volunteer in ACCU the same way he did me then I am not surprised that he did not receive the treatment he thought he was entitled to.

By the way, if materials are damaged in the post you should do two things: notify the sender and notify your local post office. If materials are regularly damaged you the problem is between you and your local postal service. For the record I receive numerous publications through an ordinary domestic letterbox and they are never damaged.

Microsoft Office Assistant

I remain convinced that the easiest way to suppress Office Assistant is to uninstall it (or never install it in the first place). The only time this is a problem is if you are using Microsoft Office on a shared machine.

Rounding Errors

I am familiar with guard digits but that cannot work in C or C++ because all the bits available are used (that is not true on all systems but it is certainly true on MSDOS and Windows based ones. The problem is not with what is being displayed but how the internal representation is being used. One reason that I tested the code all the way to declaring variables as volatile was to ensure that it could not be playing tricks with registers. The other point was that the question was raised in a specific set of circumstances relating to poorly designed legacy code. There were very few options available (apart from rewrite the entire system)

Notes: 

More fields may be available via dynamicdata ..