Journal Articles

CVu Journal Vol 11, #1 - Nov 1998 + Letters to the Editor
Browse in : All > Journals > CVu > 111 (19)
All > Journal Columns > LettersEditor (132)
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: Questions & Answers

Author: Administrator

Date: 03 November 1998 13:15:28 +00:00 or Tue, 03 November 1998 13:15:28 +00:00

Summary: 

Body: 

I have just got time to squeeze this in before midnight.

Mr R.J. Smith emailed the following question:

I work with electronic microcontrollers (PIC devices) and to be able to program in C would be useful to me as the PIC microcontroller assember has #includes, #defines and so on very similar to C. Apart from which, C is more powerful than the Microsoft BASIC and perhaps more useful in electronics than FORTRAN. I am familiar with both these languages.

I have been reading about C for about 4-6 months, making notes and so on and decided that it would be good for me to create a simple terminal program to receive information via the RS232 serial port (COMX). I have an old book called BORLAND C++ Library Reference which lists a function called:-

_bios_serialcom(_COM......

I copied the listing given in the book and I understand the code.

However, at least 11 errors are produced showing that the:

...Call to undefined function: _bios_serialcom(....); in main .......... undefined symbol '_COM_INIT' " " " '_COM_CHR7' ...etc.

The includes:

#include <bios.h>
#include <conio.h>

are in the program at the top.

I have set the paths for the include and library files to point to the correct location.

A friend of mine who was an old C programmer with years of experience said that the compiler/linker is finding the header files, but it cannot seem to find the function in the library. To prove it, he included a bogus header: #include <bios123.h> and the error message that came up was completely different, although, I did point out to him that the _int cmd, int port, char abyte where in the bios.h header file and I did not understand why it would throw up an undefined symbol for these if they were there and if was finding the bios.h okay.

I have spent two days on this problem and even though my friend tried to compile it using Borland 5 is still flagged up the same errors.

I was using Borland 4.5 on my machine.

The Help was useless to me since with 4.5 it shows only some of the bios functions but not the _bios_serialcom. However, on my friends machine using Borland 5 some help information is available and appears to be a copy of what is in the Borland C++ library I spoke of earlier. When we clicked for an example, nothing was available.

My friend did say we could probably achieve what I wanted to do by going up a level (I think he said something about windows). However, it would suit me to stay at this level for a while since I only starting out on C.

It seems to me when I have looked on the web to be very little information about this function or examples of its use. I bought a CD with what was a C++ suite of programs. All the code was there for many applications, but the serial comms was an advert for purchase of some coding for using the serial port.

Despite the function in question having its prototype in the header file (bios.h) along with others, the library routine is either missing or there is a mistake somewhere that I can't find. I repeat that I copied the code verbatim from the book, but even if you have only a few lines to include

#include <bios.h>

a few simple definitions and the troublesome _bios_serialcom it still does not work!---argh!!!

If you have come across anything like this before I would appreciate your help. I was planning to use some of the other bios calls as well. My friend says the paths are all correct and he is really puzzled!

PS I rang the user group on 01980-630032 and they said that you may be able to help. Thanks in advance.

Your editor forwarded this cry for help to three of our experts in embedded code. Unlike Mr Smith's friend, these knew their code.

Here is the brief response from Chris Hills

I think I solved it, emailed (a longer) answer to Mr Smith.

Correct it is seeing the header. However the header has a lot of #ifdef's. There is one round _bios_serialcom. It can only be used in DOS not windows or DPMI! The error is a compiler error (not a linker error so there is no library involvement)

It was finding the bios.h but just not reading the part with bios_serialcom in it.

Solution: set the BC compiler to DOS .EXE and C. (OK you could use C++ but he wants C)

Anyone found a better solution?

By the way I recommended he get C for Engineers by Brian Bramer

Now any experienced C programmer could have found that out couldn't they? Note that there is a difference between compiler and linker errors. Assuming that the function really was a function and not a macro C should have been deducing the prototype. However why did Mr Smith's friend not use grep (or a similar utility) to search for the relevant function declaration? We will never know.

Question from Dave Williams regarding a posting of mine to a newsgroup.

I've seen you make this point on a number of occasions in C Vu and, at the risk of sounding ignorant, I don't understand why C uses all upper case for const values and enums. I appreciate your example shows a silent "redefinition" of apparently const values, however I would have thought that showed up the perils of using #define more than problems with a naming convention. Maybe I have missed the point.

If you could possibly provide a reference to the C explanation I'd be very grateful - if it's been in C Vu in the past year and I've missed it, I apologise. I have looked in Dejanews and at a number of textbooks but cannot find any convincing reason to reserve all capitals for pre-processor identifiers. Indeed, Stroustrup's first enumeration example in section 4.8 of "The C++ Programming Language" uses enum { ASM, AUTO, BREAK }.

Anyway, as I said above I am probably just showing my ignorance. Any pointers to lessen that ignorance would be much appreciated.

So Bjarne isn't perfect☺ (I'll buy you a drink in Dublin, Bjarne)

The problem stems back to the fact that C makes fairly heavy use of the pre-processor because it did not have any mechanism for providing compile time constants (still doesn't because, unlike C++, const in C does not produce a constant expression (technical term meaning the compiler can use the value directly) Unfortunately there was only one set of characters available for creating identifiers. C split this up between different users/uses. For example any identifier starting with either two underscores or an underscore and an uppercase letter was deemed to belong to implementors. That rule is written into the C standard. The other one about using all uppercase for pre-processor identifiers is purely conventional.

Many self-taught programmers deduced that the convention was that named values were written in uppercase. In other words they misunderstood the reason for the convention (to keep dangerous #define identifiers distinct from all other identifiers). The result is that many C programmers use uppercase for const variables and for enum labels. C++ programmers being even less expert at C just copied them. The original convention was there for good reasons. Those reasons are just as valid today as ever they were. Even if you never use #define yourself code in included header files will. If someone uses any lowercase letters in a pre-processor identifier you have every right to complain (even if it is the C Standard's Committees unless they start with two underscores) but if you use identifiers without any lowercase letters anywhere else the resulting problems are of your own making. It is time that the gurus started setting better examples.

Quite apart from issues of readability the following guidelines will go a long way to protect your code (programmers need to be defensive):

  • Pre-processor identifiers should never include any lowercase letters

  • All other identifiers should include at least one lowercase letter.

Notes: 

More fields may be available via dynamicdata ..