I think C99 has come a long way to fix the most obvious problems in C89
(and its predecessors). I for one would be happy if more compilers would
fully start to support C99, It will be a good day when I can actually
start to use many of the new features without having to worry about
portability too much, as is the current situation.
Agreed. Although besides the mixing of declarations and statements,
I can't think of any C99 features I *use* that are lacking in C90.
I think // comments are obscene; I have no use for variable-width
arrays; any time I need an exactly 32-bit integer type, I'm probably
not writing completely portably anyway and might as well use 'int'
itself; and so on.
There's always some things that could be improved of course. My personal
wish-list would include (in no particular order):
* mandatory support for fixed-width integers (in C99, this is optional).
This would make some platforms incompatible with C; up to this
point, C has never [to my knowledge] *required* any fixed-width
data types. How about those 9-bit-byte mainframes everyone likes
to bring up?
* support for a "packed" attribute to structs, guaranteeing that no
padding occurs.
Needs elaboration. As stated, this is flatly impossible. Even
on a vanilla Win/Intel platform,
struct { char c; double d; } x;
simply *cannot* be organized to completely avoid padding. Unless
you'd just allow the compiler to throw a warning saying "Whoops!
This struct can't be 'un-padded'!" But then you'd have implementation-
defined behavior, which is basically what we have in C99 anyway.
* some mandatory semantics for floating-points types; e.g. the assurance
that integers between certain limits can be represented exactly in the
FP types (with associated constants in limits.h)
This either already exists, or would require only a small change,
I think. FP types already have mantissa and exponent parts; all
this would require would be a standard minimum mantissa length.
* deprecation of implicit casts of fp-types to integer types (perhaps
supported by a mandatory compiler warning).
No such thing as an "implicit cast." And I really don't see
the point of this one, although I have vague recollections that
you don't like any of C's implicit conversions (you heretic
malloc-caster, you!). I think warnings about "possible loss of
data" or "wider type converted to shorter type" are QoI issues
at most.
* deprecation of implicit casts of void* to other pointer types (perhaps
supported by a mandatory compiler warning). This is a desire not
likely to be shared by many here, though ;-)
Right. Not least because it would break just about every
C program written in the last 10 years. And that's a somewhat
conservative estimate.
If you want Java, you know where to find it. One of the great
things about C is that it is (IMHO) more elegant than Java, with
the latter's uber-strict typing rules and plethora of casts.
Compare a C++ client program to a Java one sometime, and marvel
at the difference. (But that's just me, and it's OT here anyway.)
* upgraded status of enum types (they are currently quite
interchangeable with ints); deprecation of implicit casts from
int to enum (perhaps supported by a mandatory compiler warning).
Agreed, it would be nice for enums to be more "special." On
the other hand, the biggest use for enums is as a drop-in replacement
for #defined integer constants, and I don't want to lose that
capability. (Yes, "constant" consts would fix *that* problem, but
that would basically turn C compilers into C++ compilers on a
complexity scale. I like the clear-cut distinction C makes between
"objects" like 'const int foo' and "values" like 'enum { foo }',
if you see what I mean.)
* a clear statement concerning the minimal level of active function
calls invocations that an implementation needs to support. Currently,
recursive programs will stackfault at a certain point, and this
situation is not handled satisfactorily in the standard (it is not
adressed at all, that is), as far as I can tell.
Agreed.
* a library function that allows the retrieval of the size of a memory
block previously allocated using "malloc"/"calloc"/"realloc" and
friends.
While this would be nice for newbies, it's redundant for Real
Programmers (tm) who know how to store numbers in variables, and
it would break lots of malloc implementations. I know, I've made
a couple. Not all the efficient malloc implementations actually
store the sizes of blocks anywhere.
Unless you think it would be acceptable for
msize(malloc(X)) > X
in some (or all) cases; then it'd still break libraries, but the
fix would be easier.
* a #define'd constant in stdio.h that gives the maximal number of
characters that a "%p" format specifier can emit. Likewise, for
other format specifiers such as "%d" and the like.
Interesting idea. This would be useful.
* a printf format specifier for printing numbers in base-2.
This, on the other hand, is kind of silly. Couldn't you
just write your own two-line function to do this? And after
base-2, what's stopping you from demanding a printf() that
can handle base-4, or base-9, or base-247? I think this is
an idea whose time will never come.
(Not to mention all those Intro Programming instructors
who would have to find a new way of introducing recursion...)
* I think I would like to see a real string-type as a first-class
citizen in C, implemented as a native type. But this would open
up too big a can of worms, I am afraid, and a good case can be
made that this violates the principles of C too much (being a
low-level language and all).
Yep.
* Normative statements on the upper-bound worst-case asymptotic
behavior of things like qsort() and bsearch() would be nice.
O(n*log(n)) for number-of-comparisons would be fine for qsort,
although I believe that would actually preclude a qsort()
implementation by means of the quicksort algorithm
Given that the Standard gives minimum bounds on the size of
any array, any *specific* qsort() implementation is O(foo) by
definition, as one can write O(foo) <= C*foo for a specific,
but very large, value of C.
In other words, I bet you can't write a loophole-free version
of this idea. And with loopholes, it's not worth changing the
existing wording.
* mandatory constants for many things that currently need to
be tested by autoconf and similar tools, e.g. endianness.
Sounds good, until I consider that the Standard doesn't even
mandate that integers *be* stored in one endianness or the other.
Surely POSIX standardized this anyway, for those platforms that
care so awful much about it.
* deprecate trigraphs. Let's end the madness once and for all.
Haven't they been deprecated yet? ;-)
* a reliable and easy way to walk over all integers in a certain
interval, including the MAX value for that type, by means of a
for loop; eg., currently
for(unsigned i=0;i<=UINT_MAX;i++) ...
doesn't work as intended.
What do you suggest? A new looping construct?

This is
an artifact of the way C handles numbers, and it won't go away
by wishing. Better to use one of the myriad ways already
standardized, e.g.
i = 0;
do {
...
} while (++i != 0);
Ugly, but functional. And I'm sure this is a FAQ anyway.
* a "reverse comma" type expression, for example denoted by
a reverse apastrophe, where the leftmost value is the value
of the entire expression, but the right-hand side is also
guaranteed to be executed.
Where's the sequence point? How on earth would this
construct possibly be useful to anybody? And who uses the
reverse apostrophe character for anything, anyway?
* triple-&& and triple-|| operators: &&& and ||| with semantics
like the 'and' and 'or' operators in python:
a &&& b ---> if (a) then b else a
a ||| b ---> if (a) then a else b
(I think this is brilliant, and actually useful sometimes).
I think something like this is a GNU C extension; IIRC
they added a?>b for "max(a,b)". Anyway, I don't see the
advantage over
result = a? b: 0; /* &&& */
(result = a) && (result = b); /* ||| */
The second one is just about as cryptic...
* a way to "bitwise invert" a variable without actually
assigning, complementing "&=", "|=", and friends.
Huh? You want to add logical-negation and arithmetic-negation
"assignment operators" while you're at it? This is a purely
vanity "improvement"; all modern compilers contain optimizers
that can optimize "i = ~i" into the equivalent of "NOT EAX"
anyway. No need to make the code illegible too.
* 'min' and 'max' operators (following gcc: ?< and ?>)
Ditto the "Huh?" This is what functions were built to
do. You know, curly braces and all that? (Question for
those who know; Chris Torek, maybe?: Do any processors
incorporate 'min' and 'max' instructions, or is the ?<
operator going to get compiled into the same thing as the
function call (inlined), anyway?)
* a div and matching mod operator that round to -infinity,
to complement the current less useful semantics of rounding
towards zero.
I think the math library may already have these. If
not, then yes, this is a good idea.
my $.02,
-Arthur