Re: Is C99 the final C? (some suggestions)

From: Keith Thompson (kst-u_at_mib.org)
Date: 12/04/03


Date: Thu, 04 Dec 2003 21:41:38 GMT

qed@pobox.com (Paul Hsieh) writes:
> In article <lnk75encj9.fsf@nuthaus.mib.org>, kst-u@mib.org says...
[...]

> > There's ample precedent in other languages (Pascal and Ada at
> > least) for packed structures. [...] You can't sensible take the
> > address of packed_obj.i. A function that takes an "int*" argument
> > will likely die if you give it a misaligned pointer (unless you
> > want to allow _Packed as an attribute for function arguments).
> > The simplest approach would be to forbid taking the address of a
> > member of a packed structure (think of the members as fat bit
> > fields). [...]
>
> Then what would be the point of even calling it a "struct"? This is
> what I am saying -- it leads to bus errors because of the rest of
> the language concepts like taking the address of any value that is
> stored in a memory location.

Surely it's no worse than calling a struct with bit fields a "struct".

> > Another possibility (ugly but perhaps useful) is to make the address of a
> > member of a packed field yield a void*.
>
> No -- the problem is with the BUS error itself. The C language
> doesn't need *EVEN MORE* ways of creating UB with otherise
> acceptable syntax. This is more than just ugly is very very
> anti-intuitive.

My thought was that making &struct_obj.packed_member yield a void*
would force the programmer to be careful about how he uses it. I
momentarily forgot about the implicit conversion from void* to any
object pointer type. (Which was dumb; I've even been participating in
the permanent floating "don't cast the result of malloc()" flameware.)

> The right answer is to give such pointers a special attribute, like,
> "_Unaligned" (or simply reuse "_Packed".)
[snip]

Yeah, that makes more sense than my idea.

BTW, I'm not necessarily arguing that packed structures would be worth
adding to the language, just thinking about how to do it right if it's
going to be done at all.

[...]
> > Agreed. The limit on call depth is typically determined by the
> > amount of available memory, something a compiler implementer can't
> > say much about. You could sensibly add a call depth clause to the
> > Translation Limits section (C99 5.2.4.1); that would the [require
> > the] implementation to handle at least one program with a call
> > depth of N, but wouldn't really guarantee anything in general.
>
> Well the problem with this is that then the *LINKER* would have to
> have augmented to analyze the max relevant stack size of all
> functions in an object and then assign the final stack according to
> a formula (N * maxstacksz) that makes this work. It also kind of
> makes use of alloca impossible.

No, adding a call depth requirement to C99 5.2.4.1 wouldn't require
any kind of analysis. There would be no guarantee that a given depth
will be supported in all cases, merely that the implementation has to
translate and execute at least one program that hits the limit (along
with all the others). If a requirement for a call depth of at least,
say, 100 were added to 5.2.4.1, it could probably be met by all
existing implementations with no changes.

[...]
> > Well, you can do that with the "%s" specifier, as long as you've
> > defined a function that returns an image string for a value of your
> > type (with all the complications of functions returning dynamic
> > strings).
>
> Who is going to free the memory allocated for this string? If its
> static, then what happens when you try to printf two such items --
> or just try to use it in a multitasking environment in general?

That's the same problem you have with any function that returns a
string. There are numerous solutions; programmers reinvent them all
the time.

If you can come up with a specification for an enhanced printf that
can produce arbitrary user-defined output for arbitrary user-defined
types, we can discuss whether it's better than "%s" with an image
function.

> > [...] If you want "min" and "max" for int, there
> > aren't any spare operator symbols you can use. If you want to allow
> > overloading for arbitrary symbols (which some languages do), you'll
> > need to decide how and whether the user can define precedence for the
> > new operators.
>
> Good point, but something as simple as "lowest precendence" and
> increasing in the order in which they are declared seems fine
> enough. Or maybe inverted -- just play with those combinations to
> see what makes sense in practice. If that's not good enough, then
> make the precedence level relative to another operator at the time
> of declaration. For example:
> int _Operator ?< after + (int x, int y) { /* max */
> if (x > y) return x;
> return y;
> }
>
> int _Operator ?> same ?< (int x, int y) { /* min */
> if (x < y) return x;
> return y;
> }

I think "increasing in the order in which they are declared" would be
very bad; you could quietly change the semantics of an expression by
reordering the declarations of the operators it uses (e.g., by
changing the order of #include directives).

For most C operators, the common rule for legible code is
"parenthesize, parenthesize, parenthesize". For user-defined
operators (if I thought they were a good idea), I'd probably advocate
not defining their precedence at all; if you want to write "x + y @ z",
you *have* to use parentheses. The next best thing might be to say
that all user-defined operators have the same precedence, perhaps just
above assignment.

People already complain that C looks like line noise; I don't think
assigning meanings to more arbitrary sequences of punctuation marks
solves anything. (And I would have thought that "?<" should be min,
and "?>" should be max.)

In the particular case of "min" and "max", I'd much rather just call
them "min" and "max". If you're going to have operator overloading,
you probably want function overloading as well. Even if you insist on
operator syntax rather than function call syntax, "a max b" is at
least as legible as "a $< b".

For most of the things that I'd want to see as operators, the existing
operator symbols are more than sufficient; for anything else, just use
identifiers.

[snip]

-- 
Keith Thompson (The_Other_Keith) kst-u@mib.org  <http://www.ghoti.net/~kst>
San Diego Supercomputer Center             <*>  <http://www.sdsc.edu/~kst>
Schroedinger does Shakespeare: "To be *and* not to be"
(Note new e-mail address)


Relevant Pages

  • Re: curious about array initialization.
    ... understanding that its through the variable declaration that we ... By "inline string", I assume you mean a string literal. ... more than that you have implicit storage. ... Its a concept from computer programming. ...
    (comp.lang.c)
  • Re: DhcpRequestParams from dhcpcsvc.dll
    ... it is because I do think that my own vb declaration is wrong, ... string to Unicode with StrConv and pass that as a string. ... Dim sendParams As DHCPAPI_PARAMS ...
    (microsoft.public.vb.winapi)
  • Re: curious about array initialization.
    ... understanding that its through the variable declaration that we ... By "inline string", I assume you mean a string literal. ... more than that you have implicit storage. ...
    (comp.lang.c)
  • Re: curious about array initialization.
    ... understanding that its through the variable declaration that we ... By "inline string", I assume you mean a string literal. ... more than that you have implicit storage. ...
    (comp.lang.c)
  • Re: boolean localization problem
    ... we're performing string concatenation on ... Test 3 is where operator precedence makes a difference. ... TypeName) & vbCrLf ...
    (microsoft.public.scripting.vbscript)

Loading