knudsen@ihwpt.ATT.COM (mike knudsen) (03/01/88)
Don't use Scanf() from the C Standard Library if you care about the size of your object program. It uses 5K (yes, 5000 bytes) of text space, plus over 200 bytes of Data. Ripping it out of my huge music editor really opened things up for new features this weekend. [Above figures are for Microware OS9 6809 C library]. It's well worth writing your own code to do simple parses. Among the string functions, try Index(char, string) which will find commas and such in the input. Input is best got from gets(string). Besides, scanf() has always been hostile to users who don't type in just the right stuff. If you need it for user-friendly stuff use gets(string) followed by sscanf(string). Note: "string" means "(char *)" or "char[]" in the above. PS: Printf() is probably just as big, but usually harder to do without, especially in a big program. -- Mike J Knudsen ...ihnp4!ihwpt!knudsen Bell Labs(AT&T) Delphi: RAGTIMER CIS: <memory failure, too many digits> "Just say NO to MS-DOS!" "OS/2 == 1/2 of an OS"
johnson@c10sd1.StPaul.NCR.COM (Wayne D. T. Johnson) (03/05/88)
In article <2401@ihwpt.ATT.COM> knudsen@ihwpt.ATT.COM (mike knudsen) writes: >Don't use Scanf() from the C Standard Library if you care >about the size of your object program. It uses 5K >(yes, 5000 bytes) of text space, plus over 200 bytes of Data. >Ripping it out of my huge music editor really opened things >up for new features this weekend. I've also noticed that printf is somwhat bulky. If you know what you are going to print out, why not print it out your self instead of using a (simple) interpreter to do it for you. Real programmers don't use printf ;-)
rk9005@cca.ucsf.edu (Roland McGrath) (03/11/88)
One real stupidity I've seen many, many times is the over-use of printf. The printf functions have their uses, and they do their job quite well, but please know what these uses are!! For example: printf("Hello world!\n"); Haven't you ever heard of puts???? puts("Hello world!"); /* note the newline is appended */ or printf("hi"); try fputs: fputs("hi", stdout); /* no newline appended */ What's that? Oh, now you have to include <stdio.h> so you can get the proper declarations of all these functions anyway? Poor baby! And the ultimate stupidity: printf("\n"); Get a brain!!!!! You're using the function that can do complex data formatted output to write one bleeping character!!!!! Try putchar('\n'); If you include <stdio.h>, this will probably end up being a macro that will write it out very fast. I have even seen: sprintf(buf, "constant string"); Hey, Mr. Power-Programmer, ever heard of strcpy???? In general, if there's no format spec, don't use printf!!!!!! -- Roland McGrath ARPA: roland@rtsg.lbl.gov roland@lbl-rtsg.arpa UUCP: ...!ucbvax!lbl-rtsg.arpa!roland
pete@wlbr.EATON.COM (Pete Lyall) (03/12/88)
In article <1185@ucsfcca.ucsf.edu> roland@rtsg.lbl.gov (Roland McGrath) writes: >One real stupidity I've seen many, many times is the >over-use of printf. > >For example: > printf("Hello world!\n"); >Haven't you ever heard of puts???? > puts("Hello world!"); /* note the newline is appended */ Hmmmm. What about the case where 'printf()' is already used elsewhere in the program for argument substitution and formatting? Wouldn't this merely be just another subroutine (in RMA) call to the already included 'printf' function? If that is in fact the case, the I would suspect that the use of 'puts()' or 'fputs()' would actually add code, unless of course the 'puts()' or 'fputs()' are used internally by 'printf()'. I doubt that this is the case (my local unix.wizard says the 'puts' brothers aren't used by 'printf()', at least not here). Another item you might consider... if you're using a coco3 under level II, the minimum allocation segment is 8k under the memory management scheme. Os9 doesn't care if the program is 79 bytes or 7900 bytes, it is still going to allocate 8192 for the program segment (or some multiple thereof). Of course the counter arguments are that if you're byte-fighting to get within the next lower 8k notch, removal of *all* printf's may do you some good (approximately 3-5k). Also, you could save some disk space by removing *all* printf's. -- Pete Lyall (OS9 Users Group VP)| DELPHI: OS9UGVP | Eaton Corp.(818)-706-5693 Compuserve: 76703,4230 (OS9 Sysop) OS9 (home): (805)-985-0632 (24hr./1200 baud) Internet: pete@wlbr.eaton.com UUCP: {ihnp4,scgvax,jplgodo,voder}!wlbr!pete
knudsen@ihwpt.ATT.COM (mike knudsen) (03/12/88)
Good points. But if you already are using printf() in your program (with a legitimate need for the formatting) in several places, then substituting puts() where possible will make your program object file bigger, not smaller, since now the puts() code has to be linked in too. Puts() and putchar() will be a little faster, but when you're talking to humans who cares? BTW, I once wrote a large interactive monitor for a free-standing 8086 board, using a C that had no I/O at all. I wrote routines to output %2x, %4x, and %5d as well as strings. Took a lot of calls to do one good printf(), but it IS possible and such custom I/O may save you bytes. -- Mike J Knudsen ...ihnp4!ihwpt!knudsen Bell Labs(AT&T) Delphi: RAGTIMER CIS: <memory failure, too many digits> "Just say NO to MS-DOS!" "OS/2 == 1/2 of an OS"
ugfailau@sunybcs.uucp (Fai Lau) (03/12/88)
In article <1185@ucsfcca.ucsf.edu> roland@rtsg.lbl.gov (Roland McGrath) writes: >One real stupidity I've seen many, many times is the >over-use of printf. The printf functions have their uses, >and they do their job quite well, but please know what these >uses are!! C'mon!!! Is it really an issue? >For example: > printf("Hello world!\n"); >Haven't you ever heard of puts???? > puts("Hello world!"); /* note the newline is appended */ I can't imagine any reasonably competant C compiler not generating the almost same codes for both cases. >or > printf("hi"); >try fputs: > fputs("hi", stdout); /* no newline appended */ >What's that? Oh, now you have to include <stdio.h> so >you can get the proper declarations of all these functions anyway? >Poor baby! <stdio.h> should be included in mostly every program just so that when you do need it you have it around. It's not gonna give you a bigger or slower program. >And the ultimate stupidity: > printf("\n"); >Get a brain!!!!! You're using the function that can do complex >data formatted output to write one bleeping character!!!!! >Try > putchar('\n'); >If you include <stdio.h>, this will probably end up being a macro >that will write it out very fast. > >I have even seen: > sprintf(buf, "constant string"); >Hey, Mr. Power-Programmer, ever heard of strcpy???? Let's face it. The best way to give efficiency to a program is to write your own macro to handle file I/O and strings. Macros like strcpy are too general if you want to be picky. For example, if you want to print a string fast, you would write a routine that uses only putc with no format capacity and no error checking whatsoever, and forget about printf. Most of what you said are true. But if one has to be as picky as you suggest, then let's forget about stdio.h and strings.h and write everything from the ground up. Fai Lau SUNY at Buffalo (The Arctic Wonderland) UU: ..{rutgers,ames}!sunybcs!ugfailau BI: ugfailau@sunybcs INT: ugfailau@joey.cs.buffalo.EDU
jv@mhres.mh.nl (Johan Vromans) (03/12/88)
In article <1185@ucsfcca.ucsf.edu> roland@rtsg.lbl.gov (Roland McGrath) writes: >One real stupidity I've seen many, many times is the >over-use of printf. The printf functions have their uses, >and they do their job quite well, but please know what these >uses are!! > > [examples of using puts, fput, putc instead of printf] > >And the ultimate stupidity: > printf("\n"); >Get a brain!!!!! You're using the function that can do complex >data formatted output to write one bleeping character!!!!! >Try > putchar('\n'); >If you include <stdio.h>, this will probably end up being a macro ... If you don't you will likely end up with a missing routine ... >that will write it out very fast. Yes. But it does not flush if the output is a terminal or line-buffered. >In general, if there's no format spec, don't use printf!!!!!! I partly agree. When you are short on space, and want to eliminate the use of "large" routines like printf, you are right. On the other hand, you suggest the use of four or five different routines (with all different calling sequences) instead of one simple and elegant "printf" routine. Printf *CAN* do complex formatting, but it *DOESN'T* do this if you don't have format strings. What remains is just the tiny overhead of testing whether there are formatting characters in the string... I dislike discussions in which the quality of the arguments is measured by the number of exclamation marks following each sentence. -- Johan Vromans | jv@mh.nl via European backbone Multihouse N.V., Gouda, the Netherlands | uucp: ..{uunet!}mcvax!mh.nl!jv "It is better to light a candle than to curse the darkness"
henry@utzoo.uucp (Henry Spencer) (03/13/88)
> For example, if you want to print a string fast, you would write > a routine that uses only putc... !!NO!! If you want to print a string fast, you use fputs and insist that your supplier implements it properly. Putc has to do things like buffer- overflow checking on every character; a fast implementation of fputs can inspect the buffer *once*, note that there is room for N more characters, copy N characters at high speed, and then update counts and so forth *once*. This is a major efficiency win over putc if you are doing it a lot. Unfortunately, not all implementors make the effort to make stdio fast. In general, System V stdios are fast and 4BSD ones are not. (There are exceptions to this, both ways, and I believe the 4BSD one is going to be improved.) -- Those who do not understand Unix are | Henry Spencer @ U of Toronto Zoology condemned to reinvent it, poorly. | {allegra,ihnp4,decvax,utai}!utzoo!henry
sef@csun.UUCP (Sean Fagan) (03/13/88)
In article <9241@sunybcs.UUCP> ugfailau@sunybcs.UUCP (Fai Lau) writes: >In article <1185@ucsfcca.ucsf.edu> roland@rtsg.lbl.gov (Roland McGrath) writes: [regarding uses of printf(3)] > C'mon!!! Is it really an issue? Yes, it can be; since printf(3) is interpreted, it *WILL* be slower than directly coding the correct statements. I.e., printf("Hello world!\n") is slower than puts("Hello world!") which is slower than write(1,"Hello world!\n",13). If you're doing a lot of I/O like this, it can be significantly slower. >>For example: [printf vs. puts] > I can't imagine any reasonably competant C compiler not >generating the almost same codes for both cases. What does a compiler have to do with a *subroutine*?! printf is a subroutine, just like any other; the compiler knows nothing about it, nor should it. (As an aside, I've thought about writing a printf compiler, but has anybody else already done that? The generated code would be larger, but, most likely, quite a bit faster...) > <stdio.h> should be included in mostly every program >just so that when you do need it you have it around. It's not >gonna give you a bigger or slower program. No, but it does eat up namespace, typedef space, you're precluded from using your own putc, getc, etc., etc. >>And the ultimate stupidity: >> printf("\n"); >>Get a brain!!!!! You're using the function that can do complex >>data formatted output to write one bleeping character!!!!! >>Try >> putchar('\n'); >>If you include <stdio.h>, this will probably end up being a macro >>that will write it out very fast. [sprintf(buf, "constant string"); instead of strcpy] > Let's face it. The best way to give efficiency to a program >is to write your own macro to handle file I/O and strings. Macros like >strcpy are too general if you want to be picky. [write own routine using putc for fast I/O] No, if one wants to do that, one doesn't use <stdio> at all; one uses write(2) (assuming you're on Unix; however, most PC C compilers support write anyway). For the most part, I don't include <stdio> in my programs at all; printf doesn't need it, and I can get by with write very easily. >Fai Lau >SUNY at Buffalo (The Arctic Wonderland) >UU: ..{rutgers,ames}!sunybcs!ugfailau >BI: ugfailau@sunybcs INT: ugfailau@joey.cs.buffalo.EDU -- Sean Fagan uucp: {ihnp4,hplabs,psivax}!csun!sef CSUN Computer Center BITNET: 1GTLSEF@CALSTATE Northridge, CA 91330 (818) 885-2790
belmonte@svax.cs.cornell.edu (Matthew Belmonte) (03/13/88)
In article <9241@sunybcs.UUCP> ugfailau@sunybcs.UUCP (Fai Lau) writes: > C'mon!!! Is it really an issue? It shouldn't be. This discussion reminds me of a time a few years ago when I was living near Washington, D.C. and someone on a local BBS decried the use of comments in source code because they increase compilation time. >In article <1185@ucsfcca.ucsf.edu> roland@rtsg.lbl.gov (Roland McGrath) writes: >>For example: >> printf("Hello world!\n"); >>Haven't you ever heard of puts???? >> puts("Hello world!"); /* note the newline is appended */ > > I can't imagine any reasonably competant [sic] C compiler not >generating the almost same codes for both cases. Imagine again. The generated code will be a push of the address of the argument (in the above examples, a constant string) onto the stack, followed by a jump-to-subroutine to the called function, either _printf or _puts. Thus, the object codes are completely disparate. But this doesn't alter the fact that IT JUST DOESN'T MAKE ENOUGH DIFFERENCE FOR THE PROGRAMMER TO CARE. printf and puts are both linear-time algorithms. printf probably takes a little longer because it has to check for embedded format strings, but it doesn't find any in this case, so the extra time is negligible. As for the space, someone already mentioned that the effect of chopping out library routines such as _printf is usually swamped by the effect of the operating system's block allocation scheme. Program images take constant space. It's only the data space that can get larger with problem size, and that's what you should be concerning yourselves with. There are some things worth devoting your time to, and there are other things better left alone. These are sometimes difficult to differentiate, but not in this case. YOU PEOPLE ARE NITPICKING. -- Matthew Belmonte Internet: belmonte@sleepy.cs.cornell.edu BITNET: belmonte@CRNLCS *** The Knights of Batman *** (Computer science 1, College 5, Johns Hopkins CTY Lancaster '87 session 1)
ccs6277@ritcv.UUCP (Cliff SKolnick) (03/14/88)
About this printf issue. If you look at the Newsgroups line, you'll see comp.sys.m6809, that is where this discussion started. This is <64K code machine. If they are talking about a CoCo usualy <720K of disk space too. Size I believe was the issue.
kim@mcrware.UUCP (Kim Kempf) (03/15/88)
In article <9241@sunybcs.UUCP>, ugfailau@sunybcs.uucp (Fai Lau) writes: >In article <1185@ucsfcca.ucsf.edu> roland@rtsg.lbl.gov (Roland McGrath) writes: >>One real stupidity I've seen many, many times is the >>... > > C'mon!!! Is it really an issue? > >>For example: >> printf("Hello world!\n"); > > I can't imagine any reasonably competant C compiler not >generating the almost same codes for both cases. > The issue here is not the code the compiler generates (its the same in either case) but the execution time expended. Given an arbitrary string to output, printf must look at each character checking for a '%' for format conversion. If no format conversions are desired, its much faster to use puts(). Furthermore, if the conversion string *does* contain a '%' and is not escaped, watch out! Consider the following: printf("It's 100%unusable!\n"); The output is unexpected at best.
johnson@c10sd1.StPaul.NCR.COM (Wayne D. T. Johnson) (03/15/88)
In article <2428@ihwpt.ATT.COM> knudsen@ihwpt.ATT.COM (mike knudsen) writes: >Good points. But if you already are using printf() in your >program (with a legitimate need for the formatting) in several >places, then substituting puts() where possible will make >your program object file bigger, not smaller, since >now the puts() code has to be linked in too. >Puts() and putchar() will be a little faster, but when you're >talking to humans who cares? > Puts and putchar may seem to be only a little faster to humans only until you use packages that do windowing and full page menus, or even redirect your output to disk (ever write out 3.5 meg using a printf?). besides, memory is cheap and getting cheaper but CPU time is still costing quite a bit. In several instances I have found that removing several printf's that were in critical paths of our code has remarkable speeded things up. -Wayne
g-rh@cca.CCA.COM (Richard Harter) (03/15/88)
Re: Should one use puts versus always using printf. Some years ago someone (I don't have a reference anymore) took a fortran compiler and modified it to compile formatted writes rather than interpreting them. The gains in execution time were modest, on the order of 1-2%, at best. Corresponding gains can be expected in C. While it is true that using puts rather than printf when applicable is faster, the execution time efficiency gained is not particularly important. As a matter of programming style, it is preferable (all other things being equal) to use a single standard mechanism rather than a variety of mechanisms. It makes programs more complicated to write, maintain, and read if a variety of mechanisms are used for the same function. This is a simplicity versus execution time tradeoff. In our situation (SMDS not CCA) portability is an issue. By policy we restrict the use of library routines to a minimum -- the only library functions which are not carefully isolated are printf and fprintf. If I don't use puts() I don't have to know whether it runs the same and interacts the same with printf() on all machines and operating systems that we deal with. This policy is reasonable for out situation; it is not necessarily relevant for others. I would also note that if execution time for I/O is truly a concern (and it sometimes is) then one should look at doing formatting by hand, i.e. building output lines directly and writing whole lines only. In summary, this is one of those little efficiencies that is not worth bothering about in most applications. -- In the fields of Hell where the grass grows high Are the graves of dreams allowed to die. Richard Harter, SMDS Inc.
karl@haddock.ISC.COM (Karl Heuer) (03/16/88)
In article <1140@csun.UUCP> sef@csun.UUCP (Sean Fagan) writes: >printf("Hello world!\n") is slower than puts("Hello world!") which is slower >than write(1,"Hello world!\n",13). Using write() instead of the stdio routines is not necessarily a win, because non-UNIX systems may still have to fiddle with e.g. NL vs. CRLF conversions. Also note that (even on UNIX) the buffering which is usually done in stdio may let you write everything with a single system call; this can make stdio faster than multiple calls to write(). >For the most part, I don't include <stdio> in my programs at all; printf >doesn't need it, and I can get by with write very easily. I once used a compiler that let me use stdin, stdout, stderr without including <stdio.h>. I included it anyway, because I knew that omitting it was not portable. If your implementation lets you use printf without <stdio.h>, fine, but don't complain too loudly if you try to port your code and it suddenly stops working. Karl W. Z. Heuer (ima!haddock!karl or karl@haddock.isc.com), The Walking Lint
djones@megatest.UUCP (Dave Jones) (03/16/88)
> In article <1185@ucsfcca.ucsf.edu> roland@rtsg.lbl.gov (Roland McGrath) writes: .. >>And the ultimate stupidity: >> printf("\n"); >>Get a brain!!!!! You're using the function that can do complex >>data formatted output to write one bleeping character!!!!! I've done this before. And I have a brain. Although I sometimes use its complex data processing function to write silly little responses to silly postings. I think I should point out that you are mistaken about this being the ultimate stupidity. The actual ultimate stupidity -- and you could look this up -- is microwave popcorn. I hope this clears the matter up satisfactorily, Dave Jones 880 Fox Lane San Jose, CA. 95131 (408) 437-9700 Ext 3227 UUCP: ucbvax!sun!megatest!djones ARPA: megatest!djones@riacs.ARPA
wynkoop@esquire.UUCP (Brett Wynkoop) (03/17/88)
Greeting folks- Just remember that this discussion started as a discussion of C under os9 on 6809 microprocessors. In many cases these boxes just have 64k of memory, and a huge 360k to 720k of disk space which must hold the os, the compiler, and all data files. This means that the discussions about C under Unix may not be very relevent to this newsgroup. ALL FLAMES TO /DEV/NULL on Unix boxes ALL FLAMES TO /NILL on OS9 boxes -Brett --------------------------------------------------------------------------- ...........rutgers!cmcl2!esquire!wynkoop CIS........72057,3720 data.......212-942-0846 300,1200,2400 8n1 voice......212-266-0741 =========================================================================== "Character is what you are in the dark" -Lord John Warfin ---------------------------------------------------------------------------
belmonte@svax.cs.cornell.edu (Matthew Belmonte) (03/17/88)
In article <46.bagpiper@oxy.UUCP> bagpiper@oxy.uucp writes: [on the subject of printf and puts, and all the other library goodies:] >These are not part of the language!! They are some external routine. The >compiler can`t do this kind of optimization. Well, not exactly. It is possible to get the compiler to do such an optimisation; it wouldn't be hard. Consider the following snatch of an attribute grammar: expr ::= ident '(' args ')' { . . /*there is a lot of code here that does other things*/ . . /*now, here's the part where we're about to emit a symbol for the printf call:*/ fprintf(outfile, "lbsr %s /*call the subroutine*/\n", $3.is_const && TypesEqual($3.type, STRING) ? "_puts" : "_printf"); . . . } ; args ::= args arg { . . /*there's code here to shove the argument onto the stack*/ $$.is_const = false; } | arg { $$.is_const = $1.is_const; $$.type = $1.type; } ; The .type and .is_const attributes are propagated up from the expressions which constitute the arguments. So, it wouldn't be much of a job to hack something like this in, if you were given the source for an existing C compiler. BUT... Mods like this can be more of a pain in the ass than they are a help. Here the programmer has no control over what library routines will end up included in his object. This compiler is fickle, and that's BAD. -- Matthew Belmonte Internet: belmonte@sleepy.cs.cornell.edu BITNET: belmonte@CRNLCS *** The Knights of Batman *** (Computer science 1, College 5, Johns Hopkins CTY Lancaster '87 session 1)
richard@aiva.ed.ac.uk (Richard Tobin) (03/18/88)
In article <1140@csun.UUCP> sef@csun.UUCP (Sean Fagan) writes: >Yes, it can be; since printf(3) is interpreted, it *WILL* be slower than >directly coding the correct statements. I.e., printf("Hello world!\n") is >slower than puts("Hello world!") which is slower than >write(1,"Hello world!\n",13). If you're doing a lot of I/O like this, it can >be significantly slower. The key phrase here is "If you're doing a lot of I/O like this". You would certainly have to execute this statement a large number of times for the interpretation to take longer than counting the characters in the string (maybe I just don't count fast :-). The computer's time is much less valuable than mine (to me, at least), so except in very rare circumstances I'm not going to think about how hard it is for the computer. I'm quite happy to put 'printf("\n")' in my programs, especially when it's surrounded by other calls to printf. Of course, printf() vs write() is also a portability question, but I'm sure there will be plenty of comments on that... -- Richard -- Richard Tobin, JANET: R.Tobin@uk.ac.ed AI Applications Institute, ARPA: R.Tobin%uk.ac.ed@nss.cs.ucl.ac.uk Edinburgh University. UUCP: ...!ukc!ed.ac.uk!R.Tobin
tp@td2cad.intel.com (t patterson) (03/18/88)
In article <2980@haddock.ISC.COM> karl@haddock.ima.isc.com (Karl Heuer) writes: >In article <1140@csun.UUCP> sef@csun.UUCP (Sean Fagan) writes: >>printf("Hello world!\n") is slower than puts("Hello world!") which is slower >>than write(1,"Hello world!\n",13). > >Using write() instead of the stdio routines is not necessarily a win, because >non-UNIX systems may still have to fiddle with e.g. NL vs. CRLF conversions. >Also note that (even on UNIX) the buffering which is usually done in stdio may >let you write everything with a single system call; this can make stdio faster >than multiple calls to write(). for those of you arguing about the relative merits of printf, puts, and write, here's some times for each of the three writing "hello world\n" to /dev/null 100,000 times on a uVAX II running Ultrix 2.0: printf 18 sec (wall-clock time, not user or sys time) puts 15 sec write 59 sec following is a script of what I did (with white space added), then the source of the three test programs. such a simple test doesn't say a whole lot. decide for yourself what it means. Script started on Thu Mar 17 13:11:17 1988 ctdone> time tprintf >/dev/null 17.3u 0.5s 0:18 98% 7+21k 0+0io 0pf+0w ctdone> time tputs >/dev/null 14.6u 0.4s 0:15 99% 4+21k 0+0io 0pf+0w ctdone> time twrite >/dev/null 5.1u 53.4s 0:59 98% 1+3k 0+0io 0pf+0w ctdone> time tprintf >/usr/tmp/t 17.4u 1.9s 0:19 98% 7+21k 5+154io 0pf+0w ctdone> time tputs >/usr/tmp/t 14.8u 1.9s 0:17 97% 3+21k 6+155io 0pf+0w ctdone> time twrite >/usr/tmp/t 4.7u 346.4s 6:02 96% 1+3k 7+192io 0pf+0w ctdone> script done on Thu Mar 17 13:23:56 1988 tprintf.c: main() { int i; for ( i = 100000; i > 0 ; i-- ) { printf("hello world\n"); } exit(0); } tputs.c: main() { int i; for ( i = 100000; i > 0 ; i-- ) { puts("hello world"); } exit(0); } twrite.c: main() { int i; for ( i = 100000; i > 0 ; i-- ) { write(1, "hello world\n", 12); } exit(0); } -- ..tp.. t patterson domain: tp%td2cad.intel.com@relay.cs.net path: {ihnp4,cbosgd,uunet}!wucs1!tp {pyramid,hoptoad}!td2cad!tp {decwrl,hplabs,oliveb}!intelca!mipos3!td2cad!tp
gwyn@brl-smoke.ARPA (Doug Gwyn ) (03/19/88)
In article <1140@csun.UUCP> sef@csun.UUCP (Sean Fagan) writes: >For the most part, I don't include <stdio> in my programs at >all; printf doesn't need it, and I can get by with write very easily. printf() most certainly does need <stdio.h> included to correctly declare its type, in general; if you haven't gotten into trouble by not having a variadic declaration in scope, it's only because you've been using implementations on relatively simple architectures. write(1,...) is not at all standard, so if you're trying to write portable applications you should stick with the standard library. You should also realize that in most cases it is more important for the source code to be maintainable that to squeeze the last bit of performance out of the hardware. This lesson was learned by most professionals in the late 1960s and early 1970s. Finally, your intuitions about what is "efficient" are wrong. I ran a test that simply printed "Hello, world!\n" 100,000 times on the standard output, on a Gould PN9080 using my SVR2 emulation, which has essentially the UNIX System V stdio implementation. I tried it three ways, using printf, fputs to stdout, and write to file descriptor 1 (in all cases using /dev/null as the output file). Here are the results: printf 5.5 seconds (user + system) fputs 4.0 seconds (user + system) write 14.2 seconds (user + system) You do gain a little by using fputs, although in a normal application (rather than an output test program) the difference would be not be significant. Note that write(1,...) is a major lossage since you lose buffering.
g-rh@cca.CCA.COM (Richard Harter) (03/20/88)
In article <296@aiva.ed.ac.uk> richard@uk.ac.ed.aiva (Richard Tobin) writes: >Of course, printf() vs write() is also a portability question, but I'm sure >there will be plenty of comments on that... Since you asked :-). People who mix printf and write are likely to be visited by things from Binkley's anxiety closet when they leave the safe haven of UNIX. If your software is going to run under any operating system other than UNIX, don't even think about doing this! Paranthetically, it is good practice to gather all of your fopens, opens, etc, together in a few well defined places in portable code. Life will be much simpler if you do. [It may be best to use standardized macros which are machine dependent, but I've never made the effort to do. If anyone has worked these out for VMS, UNIX, and PRIMOS and posts them, I will bless them.] -- In the fields of Hell where the grass grows high Are the graves of dreams allowed to die. Richard Harter, SMDS Inc.
gp@picuxa.UUCP (Greg Pasquariello X1190) (03/23/88)
In article <9241@sunybcs.UUCP>, ugfailau@sunybcs.UUCP writes: > In article <1185@ucsfcca.ucsf.edu> roland@rtsg.lbl.gov (Roland McGrath) writes: > >For example: > > printf("Hello world!\n"); > >Haven't you ever heard of puts???? > > puts("Hello world!"); /* note the newline is appended */ > > I can't imagine any reasonably competant C compiler not > generating the almost same codes for both cases. These are library calls, and although the compiler will generate approximately the same function calling sequence, the linker will link in a much larger function in printf(). > Let's face it. The best way to give efficiency to a program > is to write your own macro to handle file I/O and strings. Macros like > strcpy are too general if you want to be picky. > For example, if you want to print a string fast, you would write > a routine that uses only putc with no format capacity and no error > checking whatsoever, and forget about printf. That is about what puts() does! However, rather than looping on putc(), the string is put directly into the buffer with memcpy(), which is quicker. Greg Pasquariello ihnp4!picuxa!gp
henry@utzoo.uucp (Henry Spencer) (03/24/88)
> Paranthetically, it is good practice to gather all of your fopens, opens, > etc, together in a few well defined places in portable code... This turns out to be a good idea for another reason: if you seriously care about good-quality error handling, it almost always needs to be customized to your program to some extent, and things are much simpler if the error handling for things like fopen is centralized. -- "Noalias must go. This is | Henry Spencer @ U of Toronto Zoology non-negotiable." --DMR | {allegra,ihnp4,decvax,utai}!utzoo!henry
belmonte@svax.cs.cornell.edu (Matthew Belmonte) (03/31/88)
In article <960@micomvax.UUCP> ray@micomvax.UUCP (Ray Dunn) writes:> >Compilers do not have the ability to understand the functionality of the >procedures being called and alter the code (and arguments!) accordingly! What you mean to express by "understand the functionality" appears nebulous to me. As I said before, nothing practical prevents one from including the semantics of standard functions in compilers. Conversions from one sequence of statements to another with equivalent semantics can be expressed using attribute grammars. >Apart from anything else, the "functionality" of printf and puts is only >determined at *link* time! Again, it is unclear to me what you mean by determination of "functionality." It is true that in a typical compiler, the only optimisations done are flow-of-control optimisations (e.g. induction variables reduction in strength, live variable analysis, code motion) and computation and storage optimisations (e.g. elimination of common subexpressions, copy propagation, constant folding, register allocation) *within* the code being compiled. Calls to external functions can be treated atomically, as "black boxes" -- but there's no rule that says they *have* to be. If a function is part of a standard library, then rules can be included in the compiler for simplification of those functional expressions. To take a simple example, suppose I have a standard function called expt which takes a floating-point argument and raises it to a power. Suppose I have a functional expression "expt(x, 2)". So rather than calling in my high-powered expt function it would be much simpler to do a floating-point multiply of x*x. This is a reduction in strength which encompasses an invocation of a standard function. (Suppose I had an exponentiation operator "**" s.t. "x ** y" gives the value of expt(x, y). Then there would be no external function involved, and everything would be straightforward.) So *why* do we never see semantics of standard functions included in compilers? Because, in my opinion, it's not worth it. It makes the compiler dependent on the standard libraries. If my compiler's rules assume a particular implementation of a standard function, then if I change the implementation I'm liable to have either to change the compiler or to live with inefficient code. In summary: There is no inherent limitation of compilers which prevents their knowing about standard functions. Despite this, we never see compilers playing with standard functions, because that would create too much of a tangled mess of dependencies. So Fai Lau was being unrealistic in saying that compilers which don't do this sort of thing are unimaginable. Yet at the same time, it is wrong to assert, as Ray Dunn does, that such optimisations are impossible. Comments are welcome. -- Matthew Belmonte Internet: belmonte@sleepy.cs.cornell.edu BITNET: belmonte@CRNLCS *** The Knights of Batman *** (Computer science 1, College 5, Johns Hopkins CTY Lancaster '87 session 1)
karl@haddock.ISC.COM (Karl Heuer) (04/01/88)
[ The previous article was directed to comp.sys.m6809, but this is a language issue. I'm redirecting back to comp.lang.c. --kwzh ] In article <2108@svax.cs.cornell.edu> belmonte@sleepy.cs.cornell.edu (Matthew Belmonte) writes: >So *why* do we never see semantics of standard functions included in >compilers? Because, in my opinion, it's not worth it. It makes the compiler >dependent on the standard libraries. If my compiler's rules assume a >particular implementation of a standard function, then if I change the >implementation I'm liable to have either to change the compiler or to live >with inefficient code. I don't see that such a compiler would have to depend on the implementation; just on the functional specification (which has now been standardized). Thus, it's quite safe for a compiler to convert, say, "memcpy" into a block-copy instruction. (But a safer approach is to recognize "__builtin_memcpy" instead, and place "#define memcpy(x,y,z) __builtin_memcpy(x,y,z)" into the appropriate header file.) Btw, "never" is too strong. Some C compilers already do this inlining. With the upcoming standard, it will probably become more popular. Karl W. Z. Heuer (ima!haddock!karl or karl@haddock.isc.com), The Walking Lint
jeff@aiva.ed.ac.uk (Jeff Dalton) (04/03/88)
In article <2108@svax.cs.cornell.edu> belmonte@sleepy.cs.cornell.edu (Matthew Belmonte) writes: ] To take a simple example, suppose I have a standard function called ] expt which takes a floating-point argument and raises it to a power. ] Suppose I have a functional expression "expt(x, 2)". So rather than ] calling in my high-powered expt function it would be much simpler to ] do a floating-point multiply of x*x. ] So *why* do we never see semantics of standard functions included in ] compilers? Because, in my opinion, it's not worth it. It makes the ] compiler dependent on the standard libraries. It turns out that Lisp compilers do make such optimizations. Since just about everything is a function call in Lisp, the only way to get anything done in-line (adding numbers, say, or extracting a record field) is to compile some code that doesn't call the functions that appear to do these operations. And as long as you're doing that, you might as well make some simplifications when possible. As a result, it is difficult to make the distinction between the language and the standard library as sharp as it is in C: Lisp doesn't just say that all functions are library. However, not all functions can be optimized in this way, only ones that are allowed to be compiled in-line. The programmer often has some control over this, but details vary from Lisp to Lisp. In Common Lisp, you can declare something NOTINLINE. ] In summary: There is no inherent limitation of compilers which ] prevents their knowing about standard functions. Despite this, we ] never see compilers playing with standard functions, because that ] would create too much of a tangled mess of dependencies. The problem is that you need to know when the library routine is called and when it isn't, and this rule has to be simple and nonrandom. C does not solve this problem completely, because the user may depend on aspects of standard functions that are not part of the compiler's contract. For example, the user may want printf to provide formatted output in a certain way, not just to have certain argument and result types. -- Jeff Jeff Dalton, JANET: J.Dalton@uk.ac.ed AI Applications Institute, ARPA: J.Dalton%uk.ac.ed@nss.cs.ucl.ac.uk Edinburgh University. UUCP: ...!ukc!ed.ac.uk!J.Dalton
atbowler@watmath.waterloo.edu (Alan T. Bowler [SDG]) (04/04/88)
In article <517@picuxa.UUCP> gp@picuxa.UUCP (Greg Pasquariello X1190) writes: > These are library calls, and although the compiler will generate >approximately the same function calling sequence, the linker will link in >a much larger function in printf(). > Actually this may or may not be true. If the library implementor has carefully built his PRINTF code so that it is can be used reentrantly (i.e no statics) then it is quite likely that code in the guts of the library already references PRINTF in order to give good error messages. I.e. it may be near impossible to build a C program that does not include PRINTF. As always, there may be good reasons for not using PRINTF in a particular situtation, but blanket generalizations like "the linker will link in a much larger function in printf()" just are not true across all implementations. Make it correct first, optimize second.