EmbeddedRelated.com
Forums

problem using FILE pointer

Started by abc February 5, 2009
"Everett M. Greene" wrote:
> Rocky <RobertGush@gmail.com> writes: >> CBFalconer <cbfalco...@yahoo.com> wrote: >>> abc wrote: >>> >>>> uint8 ecg[ecg_size]=3D{0}; >>>> >>>> void main (void) >>> ^^^^___________main returns an int - say so. void is illegal. >> >> With many compilers for limited resource processors it is quite >> common to support the option of a void main() especially when >> 'returning' from main is meaningless in these cases as it was >> never actually called. (Again, to save stack space.) > > Some compilers complain if there's no return statement for the > presumed default int return value of any function. Using void > keeps the compilers quiet if nothing else.
It's still illegal, and the compiler can do anything it desires. It is very simple to put a "return 0;" in the main routine. -- [mail]: Chuck F (cbfalconer at maineline dot net) [page]: <http://cbfalconer.home.att.net> Try the download section.
George Neuner wrote:
> CBFalconer <cbfalconer@yahoo.com> wrote: >> JeffR wrote: >>> cbfalconer wrote: >>>> abc wrote: >>>> >>... snip ... >>>> >>>>> FILE *fp; >>>>> >>>>> fp=fopen("C:\Documents and Settings\btp\Desktop\pertest\ecg.txt","r"); >>>> ^___ a backslash is an escape char. Use / or \\. >>>>> >>>>> while(fp!=EOF){ >>> ^.... while( !feof(fp) ) >> >> A bad suggestion. feof(fp) only signals that an EOF has been >> detected. Before that the following fread (or getc etc.) >> statement can read invalid data. All file reading calls signal >> when they encounter EOF. > > Well, technically the functions don't "signal" - else you could > use a signal handler to catch I/O errors. But they do all > indicate errors through their return values. > > [At least if the compiler is C90 or later. If you're working > with an older compiler, you can't rely on getc/putc to return > anything meaningful if an error occurs - particularly if you > inline macro versions. Not that you should be using those > brain-dead functions anyway ... ]
Again, misinformation. getc and putc return EOF (a negative integer) on error or EOF. They are often the most efficient way to use the input system. The thing to watch out for with them is the fact that they can evaluate the FILE* parameter more than once. They are unique among the file handling routines in doing this, but it enables eliminating allocation of input buffers, without the disadvantages of not buffering. This behaviour only occurs if you let getc etc. be macros. Yes, I used the word 'signal' in a cavalier manner. -- [mail]: Chuck F (cbfalconer at maineline dot net) [page]: <http://cbfalconer.home.att.net> Try the download section.
On Tue, 10 Feb 2009 16:37:00 -0500, CBFalconer <cbfalconer@yahoo.com>
wrote:

>"Everett M. Greene" wrote: >> Rocky <RobertGush@gmail.com> writes: >>> CBFalconer <cbfalco...@yahoo.com> wrote: >>>> abc wrote: >>>> >>>>> uint8 ecg[ecg_size]=3D{0}; >>>>> >>>>> void main (void) >>>> ^^^^___________main returns an int - say so. void is illegal. >>> >>> With many compilers for limited resource processors it is quite >>> common to support the option of a void main() especially when >>> 'returning' from main is meaningless in these cases as it was >>> never actually called. (Again, to save stack space.) >> >> Some compilers complain if there's no return statement for the >> presumed default int return value of any function. Using void >> keeps the compilers quiet if nothing else. > >It's still illegal, and the compiler can do anything it desires. >It is very simple to put a "return 0;" in the main routine.
Seems wasteful to start with a call (wasted stack space) and have a non-reachable "return" instruction (wasted program memory). And it's not "illegal" unless you have a hosted environment-- see ISO/IEC 9899:1999 (E) "5.1.2.1 Freestanding environment"
George Neuner wrote:
> CBFalconer <cbfalconer@yahoo.com> wrote: >
... snip ...
> >> Again, misinformation. getc and putc return EOF (a negative >> integer) on error or EOF. > > Only for modern compilers. Sorry, but what I said is correct. > > The C90 (ANSI) library standard defined the error behavior for > fgetc and fputc and specified that getc and putc be identical > in behavior to their respective f_ functions. > > K&R defined getc/fgetc to return EOF only on end-of-file. If an > error occurred, getc/fgetc could return garbage. K&R defined > putc/fputc to return the value it wrote. You had to check errno > (or call ferror) after the I/O call to find if an error actually > occurred. In the middle 80's, leading compilers added return of > EOF to indicate an error and it was eventually written into the > 1990 ANSI standard.
Maybe so, but it seems to me there is no excuse for using pre-std compilers any more. That standard has been around for 20 years now, and the earlier public drafts for even longer.
> > I know you were around for pre-ANSI (don't know if you go back to > K&R). Maybe you've blocked it all out or maybe you had a compiler > that was cutting edge, but I assure you I used compilers well into > the middle 90's that behaved exactly as I described.
Well, I refused to use C in those days. It was too easy to make fatal errors, and I am quite capable of that. My embedded work used Pascal and assembly. Pascal to the ISO standard, btw. I first looked at C for embedded with <small C> (not sure of the name anymore) around 1976. That was published in DDJ, was integer only, and compiled itself VERY slowly. I considered revising it to use my floating point packages, and other things, but decided against it (primarily for lack of a standard).
> >> The thing to watch out for with them is the fact that they can >> evaluate the FILE* parameter more than once. They are unique >> among the file handling routines in doing this, but it enables >> eliminating allocation of input buffers, without the dis- >> advantages of not buffering. This behaviour only occurs if you >> let getc etc. be macros. > > There were other issues with the macro versions as well. Because > the return value from putc was the same as its input, some > optimizing compilers would completely elide the value return code > and instead simply copy the input value.
More reasons to use standard compliant systems. If, for some rare reasons, you are really forced to used such an ancient and faulty system, you should be well aware of those diversions. -- [mail]: Chuck F (cbfalconer at maineline dot net) [page]: <http://cbfalconer.home.att.net> Try the download section.
Rocky wrote:
> Grant Edwards <gra...@visi.com> wrote: >
... snip ...
> >> So you might as well comply with standards and do the former. > > Thanks Chuck & Grant for your input. I changed one of my projects > to int main(void) and as you suggest the compiler generates the > same code as it did for the void main(void) case.
Good. I hope this exchange also impresses other people. -- [mail]: Chuck F (cbfalconer at maineline dot net) [page]: <http://cbfalconer.home.att.net> Try the download section.
CBFalconer <cbfalconer@yahoo.com> writes:
> "Everett M. Greene" wrote: > > Rocky <RobertGush@gmail.com> writes: > >> CBFalconer <cbfalco...@yahoo.com> wrote: > >>> abc wrote: > >>> > >>>> uint8 ecg[ecg_size]=3D{0}; > >>>> > >>>> void main (void) > >>> ^^^^___________main returns an int - say so. void is illegal. > >> > >> With many compilers for limited resource processors it is quite > >> common to support the option of a void main() especially when > >> 'returning' from main is meaningless in these cases as it was > >> never actually called. (Again, to save stack space.) > > > > Some compilers complain if there's no return statement for the > > presumed default int return value of any function. Using void > > keeps the compilers quiet if nothing else. > > It's still illegal, and the compiler can do anything it desires. > It is very simple to put a "return 0;" in the main routine.
What is illegal? Is it including the void or excluding it? Including a return statement or excluding it? Putting a superfulous return statement is the way to go?
On Tue, 10 Feb 2009 17:10:02 -0500, CBFalconer <cbfalconer@yahoo.com>
wrote:

>George Neuner wrote: >> CBFalconer <cbfalconer@yahoo.com> wrote: >> >... snip ... >> >>> Again, misinformation. getc and putc return EOF (a negative >>> integer) on error or EOF. >> >> Only for modern compilers. Sorry, but what I said is correct. >> >> The C90 (ANSI) library standard defined the error behavior for >> fgetc and fputc and specified that getc and putc be identical >> in behavior to their respective f_ functions. >> >> K&R defined getc/fgetc to return EOF only on end-of-file. If an >> error occurred, getc/fgetc could return garbage. K&R defined >> putc/fputc to return the value it wrote. You had to check errno >> (or call ferror) after the I/O call to find if an error actually >> occurred. In the middle 80's, leading compilers added return of >> EOF to indicate an error and it was eventually written into the >> 1990 ANSI standard. > >Maybe so, but it seems to me there is no excuse for using pre-std >compilers any more. That standard has been around for 20 years >now, and the earlier public drafts for even longer.
Unfortunately, if you have to work with an old 8 or 16-bit chip or an integer DSP, you may find that the latest C compiler for it is still pre-ANSI. A lot of chips had compilers based on SmallC, PCC, on GCC 1.4 (the first really stable version) or on ACK 1.something. GCC didn't achieve ANSI compliance until 2.0 (~1993). I don't remember when ACK finally became ANSI but it was in the mid-90s. SmallC and PCC never got there. Even well known 16-bit chips like 8086 and 68K, which were supported by the official versions of GCC, have now been dropped from the 4.x releases. You have to use 3.x versions for them. George
George Neuner wrote:
>
... snip ...
> > Even well known 16-bit chips like 8086 and 68K, which were > supported by the official versions of GCC, have now been dropped > from the 4.x releases. You have to use 3.x versions for them.
I didn't realize that. That was Stallmans biggest mistake, IMO. I mean ignoring systems with integers smaller that 32 bits. -- [mail]: Chuck F (cbfalconer at maineline dot net) [page]: <http://cbfalconer.home.att.net> Try the download section.
On 2009-02-13, CBFalconer <cbfalconer@yahoo.com> wrote:
> George Neuner wrote: >> > ... snip ... >> >> Even well known 16-bit chips like 8086 and 68K, which were >> supported by the official versions of GCC, have now been dropped >> from the 4.x releases. You have to use 3.x versions for them.
Since when is the 68K a 16-bit chip? All the ones I've ever used had 32-bit registers. Huh? I just looked at gcc trunk at http://gcc.gnu.org/viewcvs/trunk/gcc/config/ The following "non-32-bit" targets are still there: m68hc11 avr (actually it's 8-bit) pdp11 h8300 (some sub-types are 16-bit) stormy16 picochip m68k (which _is_ a 32-bit architecture, and it's) I checked the stuff for the AVR (an 8-bit CPU), and it's got commits less than a week old.
> I didn't realize that.
I don't think it's true.
> That was Stallmans biggest mistake, IMO. I mean ignoring > systems with integers smaller that 32 bits.
There are plenty of "less than 32-bit cpus" supported by gcc. --
CBFalconer wrote:
> George Neuner wrote: > ... snip ... >> Even well known 16-bit chips like 8086 and 68K, which were >> supported by the official versions of GCC, have now been dropped >> from the 4.x releases. You have to use 3.x versions for them. >
The 8086 was never well supported by gcc - by the time gcc started to support multiple target architectures, 16-bit devices x86 were close to obsolete. Although DOS and Windows 3.1 (and parts of the Win9x family) used the 16-bit mode of the x86 devices, *real* computers running *real* operating systems used 32-bit modes. Others made branches of gcc for cores outside gcc's main target areas, including the famous DJ Delorie's port for DOS and early Windows, which had a 8086 backend. The 68K support is a different story. The 68K family has always been 32-bit, not 16-bit. It has some 16-bit features - a 16-bit external databus, and the original 68000 used a 16-bit wide ALU (running twice for 32-bit operands). But these are minor implementation details, trading speed against cost and chip size. The instruction set architecture and basic register width are what counts - it was 32-bit from its conception. The first target for the first version of gcc was the 68k, and the 68k family (now as ColdFires) is still a major target that is actively developed and improved. Most of the improvements are through generic gcc changes or ColdFire-specific changes, but they still affect compilation for the 68k. Targets are dropped from gcc after going through a period of deprecation. If there are users or developers still interested in using the old targets, they will normally be kept alive - all a user needs to do is ask. Target support only gets removed if they really are obsolete, and if it would require significant effort to keep them (therefore they often get dropped at major version changes).
> I didn't realize that. That was Stallmans biggest mistake, IMO. I > mean ignoring systems with integers smaller that 32 bits. >
Stallman has made *many* big mistakes throughout his career (inevitable, given how much he has done), and this (if it were true) is far from his biggest. It's not even remotely near to the biggest mistake in the design of gcc (that would be the intentionally plugin-hostile structure, IMHO - something that is changing at the moment). Stallman wrote gcc as a compiler for use on Unix-type systems. Unix-type systems all run with at least 32-bit processors. Therefore, gcc was aimed at targets with at least 32-bit cores. Quite simple, really. Now, of course, there are gcc ports for a (small) number of 16-bit architectures, and at least one 8-bit architecture (the AVR). There may be other ports that are outside the main tree.