Path: utzoo!attcan!uunet!husc6!bbn!inmet!ishmael!inmet!rgh From: rgh@inmet Newsgroups: comp.lang.c Subject: Re: Efficient coding considered har Message-ID: <124200010@inmet> Date: 12 Nov 88 18:28:00 GMT References: <771@wsccs.UUCP> Lines: 56 Nf-ID: #R:wsccs.UUCP:-77100:inmet:124200010:000:3194 Nf-From: inmet!rgh Nov 12 13:28:00 1988 >another teacher here loves ANSI C, and every 'enhancement' he mentions >smacks me of being Pascalish in orientation. For example, the >declaration of variables within the function parentheses will >provide the 'protection' that Pascal lovers want only if the >compiler can compile both the caller and callee at the same time. >Or the linker must be more sophisticated, using information that >is generated by the compiler. How will it be handled folks? >Either way we lose. If the compiler does it, there goes our >modular strategy of putting related functions in seperate files >from the functions that use them. But then we could always >#include C code files, which is exactly what one of the afore- >mentioned teachers required of beginning C students! But what >if I want to package a set of functions for users of equipment >I manufacture to connect to the computer and I don't want them >to have the source? Then the linker will have to do it. Will >that cost more for the compiler and linker? Apparently you've not been informed that function declarations can use the prototype notation [i.e., declaring argument types as part of the function header] as well as function definitions. This addresses all your concerns: you put a prototype function declaration in an include file, and include that in all the modules that call that function, and in the module that defines the function. The linker doesn't have to do anything special. You market your function package as an include file that declares the functions, along with the object modules that define the functions. Fairly standard practice these days is to write a .h file declaring the types, macros, functions that form the external interface of the corresponding .c file. There are potential efficiency gains in this prototype business which should interest you. In the absence of prototypes, integral arguments have to be at least int-size, and floating arguments have to be at least double-size. That is, an actual argument of type float is converted to double in the calling sequence. If the caller and callee can agree, via prototypes, that the argument really is a float, then the conversion can be omitted. More fundamentally, C implementors have had to assume that any function call might be to a function that takes a variable number of arguments (such as printf). This constrains calling sequence design in various ways. For instance, several machines have a Return instruction with a operand specifying how much data to pop off the stack. You can't use this instruction unless you know how big the argument list is, which in classical C you don't. So generally the argument list gets popped off the stack at the call site, certainly more expensive in space and often in time. Now part of the prototype syntax is specifying functions (like sprintf) that take optional trailing arguments. All other functions can be assumed to take a fixed argument list. Thus an implementor could choose to use that Return-popping-n instruction in most cases. Passing arguments in registers also becomes a more attractive implementation, for similar reasons. Randy Hudson rgh@inmet.inmet.com uunet!inmet!rgh