[comp.sys.ibm.pc] Function declarations

bobmon@iuvax.cs.indiana.edu (RAMontante) (08/20/88)

Craig Dawson asks about a program in which two routines try to call a
third, somewhat as follows:

x() { static z(); z(); }
y() { static z(); z(); }

static z() { ; }

(MSC apparently chokes; BTW, TurboC accepts it.)  My question is... Why
declare z() inside the functions x() and y()?  It doesn't make sense
that the name "z" should be localized to these code blocks, since it
has to be global to the entire file (at least) anyway.  Nor do I see
the value of making it a static name, since it references an object
that can't go away or be "reclaimed" outside of x() or y(), namely a
function.  Craig's "fix", declaring static z() prior to and outside of
both x() and y() (an almost-protoype kind of declaration), seems like
the only natural thing to do.

Note:  I understand why local variables are good.  But it seems pointless
to treat the function name as "local", since it must refer to a nonlocal
object.  What am I missing?  Is there a relevant section of K&R I should
read?
-- 
--    bob,mon			(bobmon@iuvax.cs.indiana.edu)
--    "Aristotle was not Belgian..."	- Wanda

chris@mimsy.UUCP (Chris Torek) (08/21/88)

In article <11879@iuvax.cs.indiana.edu> bobmon@iuvax.cs.indiana.edu
(RAMontante) writes:
>... somewhat as follows:
>x() { static z(); z(); }
>y() { static z(); z(); }
>static z() { ; }
>
>(MSC apparently chokes; BTW, TurboC accepts it.)  My question is... Why
>declare z() inside the functions x() and y()? ... declaring static z()
>prior to and outside of both x() and y() ... seems like the only natural
>thing to do.

Why do some people like a certain 181-novel 1930s and 1940s SF pulp
series?  The only answer is `style':  Some people just do.  (Incidentally,
with the publication of `In Hell, Madonna' as `The Red Spider', now there
are 182.)

(Now I wonder how many people will recognise the series named above...)
-- 
In-Real-Life: Chris Torek, Univ of MD Comp Sci Dept (+1 301 454 7163)
Domain:	chris@mimsy.umd.edu	Path:	uunet!mimsy!chris

jfh@rpp386.UUCP (The Beach Bum) (08/22/88)

In article <11879@iuvax.cs.indiana.edu> bobmon@iuvax.UUCP (RAMontante) writes:
>Craig Dawson asks about a program in which two routines try to call a
>third, somewhat as follows:
>
>x() { static z(); z(); }
>y() { static z(); z(); }
>
>static z() { ; }
>
>(MSC apparently chokes; BTW, TurboC accepts it.)  My question is... Why
>declare z() inside the functions x() and y()?  It doesn't make sense
>that the name "z" should be localized to these code blocks, since it
>has to be global to the entire file (at least) anyway.  Nor do I see
>the value of making it a static name, since it references an object
>that can't go away or be "reclaimed" outside of x() or y(), namely a
>function.  Craig's "fix", declaring static z() prior to and outside of
>both x() and y() (an almost-protoype kind of declaration), seems like
>the only natural thing to do.

the msc compiler is broken.  the code should compile without error
as written (more or less ...)

as for the Rational behind why this is being done, ask the programmer.
the minimalist coding would be

static z();

x() { z(); }
y() { z(); }
static z() { ; }

a possible rationality behind his coding in the fashion he did is
that the functions were actually much larger than what we have above
and he wanted to indicate that the functions x() and y() were both
dependent on z().  as for why z() is declared to be static, any
number of reasons exist.
-- 
John F. Haugh II                 +--------- Cute Chocolate Quote ---------
HASA, "S" Division               | "USENET should not be confused with
UUCP:   killer!rpp386!jfh        |  something that matters, like CHOCOLATE"
DOMAIN: jfh@rpp386.uucp          |         -- apologizes to Dennis O'Connor

suitti@haddock.ima.isc.com (Steve Uitti) (08/22/88)

In article <5680@rpp386.UUCP> jfh@rpp386.UUCP (The Beach Bum) writes:
>In article <11879@iuvax.cs.indiana.edu> bobmon@iuvax.UUCP (RAMontante) writes:
>>Craig Dawson asks about a program in which two routines try to call a
>>third, somewhat as follows:
>>
>>x() { static z(); z(); }
>>y() { static z(); z(); }
>>
>>static z() { ; }
>>
>>(MSC apparently chokes; BTW, TurboC accepts it.)  My question is... Why
>>declare z() inside the functions x() and y()?

	Supporting other peoples code is more difficult than
supporting your own.  A thirty file program where everything (that can
be) is declared static is much easier to support than one that
doesn't.  "ctags", "grep", and cxref only do so much for you.
	The tighter the scope of each variable and function, the
better.  I generally try to declare the functions before all uses:
static z(a) int a; { ; }
static y() { z(5); }
static x() { y(); z(); }
main() { x(); }
	Kind of reminds you of Pascal (except that you can tell where
"main" starts).  The complexity of a program at any point seems to be
tied exponentialy to the number of variables and functions available
to it at that point.
	Unfortunately, the compilers that I've used that support
prototypes don't "automatically generate" them using this style.  If I
want prototypes for the above, I need:
static z(a) int a; { ; }
#ifdef PROTOTYPES_SUPPORTED
static z(int a); /* prototype for z() */
#endif /* PROTOTYPES_SUPPORTED */
static y() { z(5); }
static x() { y(); z(); }
main() { x(); }
	Which is too bad, since it really has all the info it could
possibly want, and I'll probably just screw up the prototype (since I can).

	On PDP-11's, the linker (ld) can run out of symbol space for
the symbol table if you don't do this.  Generally, the larger editors
that have been ported to this machine got hundreds of routines
declared "static", just to allow compilation.  This wasn't "bad".  It
made the products easier to maintain.

	Another favorite is this:
y() { z(); }
static z() { ; }
	This often yields something like "redeclaration of z".  The
first reference defaults to something like "extern int z();" for a
declaration.  I've always thought that this was a language feature.
It encourages better behaviour without requiring it.  Of course the
following is fine:
static z() { ; }
y() { z(); }

	Stephen

scjones@sdrc.UUCP (Larry Jones) (08/23/88)

In article <5680@rpp386.UUCP>, jfh@rpp386.UUCP (The Beach Bum) writes:
> In article <11879@iuvax.cs.indiana.edu> bobmon@iuvax.UUCP (RAMontante) writes:
> >Craig Dawson asks about a program in which two routines try to call a
> >third, somewhat as follows:
> >
> >x() { static z(); z(); }
> >y() { static z(); z(); }
> >
> >static z() { ; }
> >
> >(MSC apparently chokes; BTW, TurboC accepts it.) 
> 
> the msc compiler is broken.  the code should compile without error
> as written (more or less ...)

NO!!!  Amazingly enough, MSC got this right - the code is wrong.  Think about
this similar code:
  x() { static z[]; z[0] = 3; }
  y() { static z[]; z[0] = 5; }

  static z[10];
You wouldn't expect that to work, would you?  If something is declared within
a block, it must be defined within the same block unless it is declared extern.
Since you can't define functions within a block, you can't declare a static
function within a block.  Sorry.

----
Larry Jones                         UUCP: uunet!sdrc!scjones
SDRC                                      scjones@sdrc
2000 Eastman Dr.                    BIX:  ltl
Milford, OH  45150                  AT&T: (513) 576-2070
Nancy Reagan on superconductivity: "Just say mho."

markro@microsoft.UUCP (Mark Roberts) (08/25/88)

In article <356@sdrc.UUCP> scjones@sdrc.UUCP (Larry Jones) writes:
>NO!!!  Amazingly enough, MSC got this right - the code is wrong.

Thanks for the answer; here is (I believe) the appropriate section from the
May 88 draft standard (3.5.1, pg 56, lines 19-20):

  "The declaration of an identifier for a function that has block scope
   shall have no explicit storage-class specifier other than extern."

[ Amazingly? (:-) ]

haugj@pigs.UUCP (Joe Bob Willie) (08/25/88)

In article <1757@microsoft.UUCP> microsof!markro writes:
>In article <356@sdrc.UUCP> scjones@sdrc.UUCP (Larry Jones) writes:
>>NO!!!  Amazingly enough, MSC got this right - the code is wrong.
>
>Thanks for the answer; here is (I believe) the appropriate section from the
>May 88 draft standard (3.5.1, pg 56, lines 19-20):
>
>  "The declaration of an identifier for a function that has block scope
>   shall have no explicit storage-class specifier other than extern."

is it too late to get this changed back in the standard?  this seems to
be a serious mis-feature.  i have used function declarations inside
of functions to document where a function is used.  now they are telling
us we can't document static functions in this fashion.

i know this has been discussed before, but what exactly is The Committee
trying to do to C?  this one change will result in virtually all of the
code i've written being broken.  [ along with much code i've not written
but still have to maintain ]  the resulting language will share only the
name with the original language.
-- 
 jfh@rpp386.uucp	(The Beach Bum at The Big "D" Home for Wayward Hackers)

                              "ANSI C: Just say no"
                                                -- Me.

bill@proxftl.UUCP (T. William Wells) (08/26/88)

A random point on prototypes: we have the need to include
prototypes in our code while still being able to compile the code
with compilers that did not support prototypes.

The solution is this: first, all function arguments are of a type
for which the argument widening action is null.  (ints are OK,
short is not.) Second, we have, in a global include file,
something like this:

	/* Configuration section */

	#define ANSI_PROTO      /* This line would be added if the
				   compiler has prototypes.  Note that
				   just using __STDC__ is not sufficient,
				   as there are many compilers that have
				   prototypes but do not define it.  */

	/* This stuff is buried somewhere deep in the include file, the
	   person compiling our code does not look at it. */

	#ifdef ANSI_PROTO
	#define FUNC(n,p) n p;
	#else
	#define FUNC(n,p) n ();
	#endif

This is the code that makes use of the prototype macro.

	#include <our_file.h>

	FUNC(int function, (int arg1, int arg2))

What happens is that, in the default file we ship, ANSI_PROTO is
not specified and the FUNC macro will expand into something like

	extern int function();

And, since we use the right argument types, this will work on
non-ANSI or ANSI compilers.  If, however, the user *does* define
ANSI_PROTO, the FUNC macro expands to

	extern int function(int arg1, int arg2));

and he gets the type checking benefits of the prototype.


---
Bill
novavax!proxftl!bill

iiit-sh@cybaswan.UUCP (Steve Hosgood) (08/31/88)

In article <1757@microsoft.UUCP> microsof!markro writes:
>..... here is (I believe) the appropriate section from the
>May 88 draft standard (3.5.1, pg 56, lines 19-20):
>
>  "The declaration of an identifier for a function that has block scope
>   shall have no explicit storage-class specifier other than extern."
 
In article <371@pigs.UUCP> haugj@pigs.UUCP (Joe Bob Willie) writes:
>is it too late to get this changed back in the standard?  this seems to
>be a serious mis-feature.  i have used function declarations inside
>of functions to document where a function is used.  now they are telling
>us we can't document static functions in this fashion.
>
>i know this has been discussed before, but what exactly is The Committee
>trying to do to C?  this one change will result in virtually all of the
>code i've written being broken.  [ along with much code i've not written
>but still have to maintain ]  the resulting language will share only the
>name with the original language.

I agree, Joe Bob, I've got the same problem exactly! This had better get
to the the comp.std.c group *now* so they can discuss it before it *is*
too late.

I think the compiler is correct according to the standard, but the standard
is broken. However, the compiler *ought* to produce an error message. After
all, declaring a function static within a block would mean that it would
have to be *defined* within that block in order to be both visible and
usable. However, C has no mechanism for declaring functions within blocks,
so at very least the static declaration should cause an error message to that
effect.

Someone's pinched my K&R, but I'm sure it says that this is a special case
for the reasons I've mentioned above. ANSI have *got* to decide one way or
another, I hope they change lines 19-20, page 56!

I hope no-one objects, but I've directed follow-ups to comp.std.c
Even if ANSI are right, I think you'd agree that this is a standards problem
now, not just MSC.

-----------------------------------------------+------------------------------
Steve Hosgood BSc,                             | Phone (+44) 792 295213
Image Processing and Systems Engineer,         | Fax (+44) 792 295532
Institute for Industrial Information Techology,| Telex 48149
Innovation Centre, University of Wales, +------+ JANET: iiit-sh@uk.ac.swan.pyr
Swansea SA2 8PP                         | UUCP: ..!ukc!cybaswan.UUCP!iiit-sh
----------------------------------------+-------------------------------------
            My views are not necessarily those of my employers!

mouse@mcgill-vision.UUCP (der Mouse) (09/01/88)

In article <371@pigs.UUCP>, haugj@pigs.UUCP (Joe Bob Willie) writes:
> In article <1757@microsoft.UUCP> microsof!markro writes:
>> In article <356@sdrc.UUCP> scjones@sdrc.UUCP (Larry Jones) writes:
>>> NO!!!  Amazingly enough, MSC got this right - the code is wrong.
>> [F]rom the May 88 draft standard (3.5.1, pg 56, lines 19-20):
>>  "The declaration of an identifier for a function that has block
>>   scope shall have no explicit storage-class specifier other than
>>   extern."
> i have used function declarations inside of functions to document
> where a function is used.  now they are telling us we can't document
> static functions in this fashion.

Not at all; just that you can't mention that they're static in the
block.  I *would* be surprised to find that there's anything wrong with
something like

foo()
{
 ...
  { double glurf(char*,int);
    ...
  }
 ...
}

static double glurf(char *s,int maxlen)
{
 ...
}

You're confusing the two meanings of the static keyword.  When used
inside a function, `static' means one thing: the object being declared
has static storage class.  Here, `static' really is a storage class
specifier.  Outside a function, `static' means something else: the name
being declared is to be accessible only from within the file the
definition appears in.  Here, it's really a linkage specifier rather
than a storage class specifier.

In retrospect, I think it was probably a mistake to overload `static'
this way, but it is certainly far too late to change it now.

					der Mouse

			old: mcgill-vision!mouse
			new: mouse@larry.mcrcim.mcgill.edu

chris@mimsy.UUCP (Chris Torek) (09/01/88)

In article <1275@mcgill-vision.UUCP> mouse@mcgill-vision.UUCP (der Mouse)
writes:
>... I *would* be surprised to find that there's anything wrong with
>something like

[compressed vertically]

>foo() { ... { double glurf(char*,int); ... } }
>static double glurf(char *s,int maxlen) { ... }

Surprise!

According to the dpANS, the first declaration of a static function must
label that function as static.  Now we also know (from the discussion
chain in the references: line) that function declarations within other
functions may not be labelled `static'.  Putting these together, the
*only* legal ways to write this are:

	static double glurf(char *, int);
	foo() { ... /* call glurf */ ... }
	static double glurf(char *s, int maxlen) { ... }

or

	static double glurf(char *s, int maxlen) { ... }
	foo() { ... /* call glurf */ ... }
-- 
In-Real-Life: Chris Torek, Univ of MD Comp Sci Dept (+1 301 454 7163)
Domain:	chris@mimsy.umd.edu	Path:	uunet!mimsy!chris

bill@proxftl.UUCP (T. William Wells) (09/03/88)

In article <13344@mimsy.UUCP> chris@mimsy.UUCP (Chris Torek) writes:
: Surprise!
:
: According to the dpANS, the first declaration of a static function must
: label that function as static.  Now we also know (from the discussion
: chain in the references: line) that function declarations within other
: functions may not be labelled `static'.  Putting these together, the
: *only* legal ways to write this are:
:
:       static double glurf(char *, int);
:       foo() { ... /* call glurf */ ... }
:       static double glurf(char *s, int maxlen) { ... }
:
: or
:
:       static double glurf(char *s, int maxlen) { ... }
:       foo() { ... /* call glurf */ ... }

Yes. Shriek! Scream! Shout! Curse! Puke! etc.................................

All in the name of easing a few implementers' lives.

Shame on you X3J11.

---

To change the subject slightly: a new hire was asking me if he
could use some macros to encapsulate some flag setting.

I told him no.

Why?

Because the only purpose of the macro was to decrease the number
of keystrokes *he* had to use.  But it would have made the next
reader of the code have to understand two different things, the
macro AND the flag, to understand the code, instead of one.

He asked me why.  I said: this code will be written once and read
many hundred times.  Whose job do you think ought to be made
easier: yours or that future reader (who may be yourself, several
times)?  He got the point.

How is this relevant, you might ask?

Well, consider the related question: who should have to deal with
the pain caused by systems that make one pass compilation
difficult: every user of ANSI C, or those people charged with the
writing of a C compiler for those systems?

It seems that the committee forgot this.

For shame!

(And yes, even though I think the committee has done a generally
good job, I will take every opportunity to condemn them for this
egregious lapse.)

---
Bill
novavax!proxftl!bill

james@bigtex.uucp (James Van Artsdalen) (09/05/88)

In article <697@proxftl.UUCP>, bill@proxftl.UUCP (T. William Wells) wrote:

> All in the name of easing a few implementers' lives.

> Shame on you X3J11.

> [...] who should have to deal with the pain caused by systems that
> make one pass compilation difficult: every user of ANSI C, or those
> people charged with the writing of a C compiler for those systems?

It's worse than all that.  ANSI C permits conflicting function
declarations without a warning - indeed it is required that no warning
be given.  For example, consider the following in the context of a far
memory model on the 286:

int
a()
{
	int b();

	return b();
}

char *
b()
{
	return "foo";
}

A purely ANSI C compiler must not generate an error according to ANSI
C, because the incorrect declaration of b() is hidden within the scope
of a().  Yet this program cannot work, and I can't conceive of any
implementation where the ANSI C requirement is actually useful.  The
nature of functions in C is such that the *definitions* cannot be
scoped (ie, you can't place a function definition within the scope of
another function as you can in Pascal): it is not clear why it is
desirable that function *declarations* should be subject to scoping.

I too think that the ANSI C committee did a very good job overall.
-- 
James R. Van Artsdalen    ...!uunet!utastro!bigtex!james     "Live Free or Die"
Home: 512-346-2444 Work: 328-0282; 110 Wild Basin Rd. Ste #230, Austin TX 78746

tif@cpe.UUCP (09/06/88)

Written  6:40 pm  Sep  4, 1988 by bigtex.UUCP!james in cpe:comp.sy.ibm.pc
>It's worse than all that.  ANSI C permits conflicting function
>declarations without a warning - indeed it is required that no warning
>be given. ...
>... and I can't conceive of any
>implementation where the ANSI C requirement is actually useful.

I can.  When you want to use a return value in more than one way.

a() {
	int *malloc(), *x;
	x = malloc(sizeof(int));
}

b() {
	long *malloc(), *x;
	x = malloc(sizeof(long));
}

			Paul Chamberlain
			Computer Product Engineering, Tandy Corp.
			{convex,killer}!ninja!cpe!tif

haugj@pigs.UUCP (The Beach Bum) (09/09/88)

In article <12400016@cpe> tif@cpe.UUCP writes:
>Written  6:40 pm  Sep  4, 1988 by bigtex.UUCP!james in cpe:comp.sy.ibm.pc
>>It's worse than all that.  ANSI C permits conflicting function
>>declarations without a warning - indeed it is required that no warning
>>be given. ...
>>... and I can't conceive of any
>>implementation where the ANSI C requirement is actually useful.
>
>I can.  When you want to use a return value in more than one way.

bad move.  if the return value is actually (char *), declaring the
function to return (long *) is NOT going to have the same effect
as an explicit cast in all situations.

various C compilers return pointers in one register and non-pointers
in another.  the system v/68k compiler from motorola comes to mind
as one which has behavior like this.  other machines have different
formats for pointers to different objects.

the CORRECT, PORTABLE, method is to correctly declare the return
value and then cast the result.
-- 
=-=-=-=-=-=-=-The Beach Bum at The Big "D" Home for Wayward Hackers-=-=-=-=-=-=
               Very Long Address: John.F.Haugh@rpp386.dallas.tx.us
                         Very Short Address: jfh@rpp386
                           "ANSI C: Just say no" -- Me

mouse@mcgill-vision.UUCP (der Mouse) (09/11/88)

In article <13344@mimsy.UUCP>, chris@mimsy.UUCP (Chris Torek) writes:
> In article <1275@mcgill-vision.UUCP> mouse@mcgill-vision.UUCP (der Mouse) writes:
>> I *would* be surprised to find that [this doesn't work]
>> foo() { ... { double glurf(char*,int); ... } }
>> static double glurf(char *s,int maxlen) { ... }
> Surprise!

You have such a lovely way of phrasing things, Chris... :-)

> Putting these together, the *only* legal ways to write this are:

> 	static double glurf(char *, int);
> 	foo() { ... /* call glurf */ ... }
> 	static double glurf(char *s, int maxlen) { ... }
> or
> 	static double glurf(char *s, int maxlen) { ... }
> 	foo() { ... /* call glurf */ ... }

Since the whole idea was to document the fact that foo calls glurf,
near the point of call (ie, in foo), how about:

	static double glurf(char *, int);
	foo() { double glurf(char *, int); ... /* call glurf */ ... }
	static double glurf(char *s, int maxlen) { ... }

Is this permitted?

					der Mouse

			old: mcgill-vision!mouse
			new: mouse@larry.mcrcim.mcgill.edu

james@bigtex.uucp (James Van Artsdalen) (09/12/88)

In article <12400016@cpe>, tif@cpe.UUCP wrote:

| I can.  When you want to use a return value in more than one way.

| a() {
| 	int *malloc(), *x;
| 	x = malloc(sizeof(int));
| }
|
| b() {
| 	long *malloc(), *x;
| 	x = malloc(sizeof(long));
| }

This won't work right: it's not at all portable.  It assumes that
sizeof(int *) == sizeof(long*), an assumption which isn't always true.
-- 
James R. Van Artsdalen    ...!uunet!utastro!bigtex!james     "Live Free or Die"
Home: 512-346-2444 Work: 328-0282; 110 Wild Basin Rd. Ste #230, Austin TX 78746

gordon@sneaky.TANDY.COM (Gordon Burditt) (09/12/88)

In article <12400016@cpe>, tif@cpe.UUCP writes:
> Written  6:40 pm  Sep  4, 1988 by bigtex.UUCP!james in cpe:comp.sy.ibm.pc
> >It's worse than all that.  ANSI C permits conflicting function
> >declarations without a warning - indeed it is required that no warning
> >be given. ...

Error:  a diagnostic message that indicates that the program is 
	non-conforming.  Error messages are required by the standard under
	appropriate circumstances.  Examples:  "syntax error, line 127",
	"undeclared variable 'foo', line 64", and "include file 'foo.h' 
	cannot be opened".  Normally an error prohibits linking and
	execution of the program.
Warning:  a diagnostic message that does not indicate that the program is
	non-conforming.  The presence of a warning must not prohibit the
	program from being run.  

ANSI C does not anywhere prohibit warnings for any idiotic or non-idiotic
reason whatsoever:
Warning - source program contains the character 'm'.
Warning - use of single-character variable names - docking your paycheck $50.00
Warning - statement not reached
Warning - source program contains the character 'a'.
Compilation complete, 0 errors, 1 warnings, job cost $8.37
Warning - obscene variable name - naughty, naughty.
Warning - implicit conversion from long to int may lose precision.
Gag, barf, bletch - trigraphs used.  Ick!
Warning - indentation style does not match braces.
Warning - numeric constant 3.14 is an inaccurate approximation for pi.
Warning - division by three.
Warning - numeric constant used - using a #define is preferred style.
Warning - supplied MasterCard number is within $10.00 of credit limit.
Warning - spelling error in comment.
Warning - no warnings generated
Warning - comments do not match code
Warning - non-K&R I indentation style used
Some existing compilers produce single-character warnings on every character
in the code, paginated and with line numbers.  This is sometimes referred to
as a "compiler listing".

> >... and I can't conceive of any
> >implementation where the ANSI C requirement is actually useful.
> I can.  When you want to use a return value in more than one way.
> a() {
> 	int *malloc(), *x;
> 	x = malloc(sizeof(int));
> }
> 
> b() {
> 	long *malloc(), *x;
> 	x = malloc(sizeof(long));
> }

At least one of these calls is likely to return garbage.  Besides the
problem that there is no guarantee that int * and long * have the same
size, format, byte ordering, or bit ordering, every sane (read:  how I would 
write it if my supply of drugs holds out :-) ) *86 compiler returns a 
(far) char * in ES:AX, and a (far) long * in ES:DX.  Naturally, (far) unsigned 
char * is returned in AX:DX, and (far) unsigned long * in DX:AX.  (far) int * 
is returned in BX:AX and short * is returned in CX:DX (Yes, even if short and 
int are the same size!)

I think mismatched declarations like this ought to be a "common warning",
even if it isn't an error.

Regardless of what you think of the above linkage conventions, the
implementer is still permitted to do this.  Taking a more real example,
on some 68000 implementations, pointers are returned in a0 and integers
(of various sizes) are returned in d0.  Since Berkeley and USG systems
disagree over whether sprintf() returns the (char *) buffer given in the 
first argument or the (int) number of characters written in the buffer,
someone wrote an assembly-language version of sprintf() that returned both 
values.  Assuming that all programs that use the return value declare it 
correctly (dream on!), they could all get the expected return value.
Cute, but unportable in the extreme!

Another possibility for 8086 systems (which DO NOT have a protected mode!):  
Require that all structures and unions line up on a 16-byte boundary.
Now, make a far struct pointer *16 BITS* - what you would load into the
segment register to access it with an offset of 0.  This is, of course,
very different from the 16-bit near pointer, even if it is the same size.
Pointers to ints, chars, etc. would still require at least a 24-bit (and
probably 32-bit, for convenience of representation) far pointer.  You could 
save some code making references like structptr->foo this way.  Since it
isn't upward-compatible to protected mode, compiler-writers aren't likely
to do this.


				Gordon L. Burditt
				...killer!ninja!sneaky!gordon

iiit-sh@cybaswan.UUCP (Steve Hosgood) (09/13/88)

In article <12400016@cpe> tif@cpe.UUCP writes:
>bigtex.UUCP!james in cpe:comp.sy.ibm.pc writes:
>>It's worse than all that.  ANSI C permits conflicting function
>>declarations without a warning - indeed it is required that no warning
>>be given. ...
>>... and I can't conceive of any
>>implementation where the ANSI C requirement is actually useful.
>
>I can.  When you want to use a return value in more than one way.

[ example deleted ]

Yeah, but surely the *storage class* of the function declaration shouldn't
be allowed to conflict?

The example showed good use of conflicting *types*, can anyone justify having
the same name declared 'static' and 'extern' in the same file? I can't.

-----------------------------------------------+------------------------------
Steve Hosgood BSc,                             | Phone (+44) 792 295213
Image Processing and Systems Engineer,         | Fax (+44) 792 295532
Institute for Industrial Information Techology,| Telex 48149
Innovation Centre, University of Wales, +------+ JANET: iiit-sh@uk.ac.swan.pyr
Swansea SA2 8PP                         | UUCP: ..!ukc!cybaswan.UUCP!iiit-sh
----------------------------------------+-------------------------------------
            My views are not necessarily those of my employers!

gary@apexepa.UUCP (Gary Wisniewski) (09/13/88)

In article <12400016@cpe> tif@cpe.UUCP writes:
>
>Written  6:40 pm  Sep  4, 1988 by bigtex.UUCP!james in cpe:comp.sy.ibm.pc
>>It's worse than all that.  ANSI C permits conflicting function
>>declarations without a warning - indeed it is required that no warning
>>... and I can't conceive of any
>>implementation where the ANSI C requirement is actually useful.
>
>I can.  When you want to use a return value in more than one way.
>
>a() {
>	int *malloc(), *x;
>	x = malloc(sizeof(int));
>}
>
>b() {
>	long *malloc(), *x;
>	x = malloc(sizeof(long));
>}

You can get away with this, but donn your asbestos suit if you say this
in comp.lang.c!  This won't work for machines which have different
pointer formats for different data types.

	char *malloc();
	long *x;
	x = (long *) malloc(sizeof(long));

The above tells the compiler that it needs to explicitly coerce a
char* to a long*.  Your code above just assumes that malloc returns
a long*; not valid on many machines (Data General, for instance).
-- 
Gary J. Wisniewski				  Apex Software Corporation
{allegra,bellcore,cadre}!pitt!darth!apexepa!gary  Phone: (412) 681-4343