Has thought been given given to a cleaned up C? Possibly called C+.

  • Thread starter Casey Hawthorne
  • Start date
K

Keith Thompson

Rod Pemberton said:
Rod Pemberton a écrit :
[...]

Do the typical macro definitions of offsetof() (e.g., C Rationale or
X11?) work correctly with LCC-Win32? That strongly suggests to me
they don't.

If they do, then there is no need for sizeof(). Only slight
adjustment of an existing struct is required. Structs can also be
constructed to determine the size of other types. If one is
paranoid about incorrect value due to alignment issues, then one
could do multiple checks.

I think I see what you're trying to say.

The offsetof() macro itself is of no help as a sizeof replacement, but
the typical definition of the offsetof() macro can be adapted for that
purpose by means of some ugly pointer arithmetic trickery. Here's a
small program that demonstrates the method:

#include <stdio.h>
#include <time.h>

#define SIZE_OF_TYPE(type) \
((size_t)((char*)((type(*)[1])0 + 1) - \
(char*)(type(*)[1])0))

#define SIZE_OF_OBJECT(obj) \
((size_t)((char*)(&(obj) + 1) - (char*)&(obj)))

int main(void)
{
int int_obj;
double double_obj;
struct tm tm_obj;
int n = 42;
float vla[n];

printf("SIZE_OF_TYPE(int) = %lu\n",
(unsigned long)SIZE_OF_TYPE(int));
printf("SIZE_OF_TYPE(double) = %lu\n",
(unsigned long)SIZE_OF_TYPE(double));
printf("SIZE_OF_TYPE(struct tm) = %lu\n",
(unsigned long)SIZE_OF_TYPE(struct tm));
putchar('\n');

printf("sizeof(int(*)[4]) = %lu\n",
(unsigned long)sizeof(int(*)[4]));
putchar('\n');

printf("SIZE_OF_OBJECT(int_obj) = %lu\n",
(unsigned long)SIZE_OF_OBJECT(int_obj));
printf("SIZE_OF_OBJECT(double_obj) = %lu\n",
(unsigned long)SIZE_OF_OBJECT(double_obj));
printf("SIZE_OF_OBJECT(tm_obj) = %lu\n",
(unsigned long)SIZE_OF_OBJECT(tm_obj));
printf("SIZE_OF_OBJECT(vla) = %lu\n",
(unsigned long)SIZE_OF_OBJECT(vla));

return 0;
}

Of course these macros have some significant drawbacks:

Separate macros are required for ``sizeof (type)'' and ``sizeof
object''.

SIZE_OF_OBJECT() applies only to lvalues.

SIZE_OF_OBJECT evaluates its argument twice (compared to the built-in
"sizeof" operator, which doesn't evaluates its argument at all
unless it's a VLA).

SIZE_OF_OBJECT cannot be applied to certain complex type names,
such as int(*)[4]. This can be worked around by adding a typedef.

Both macros invoke undefined behavior when expanded, just
as an expansion of the usual definition of offsetof() does.
Like offsetof(), they're likely to work on most implementations.

They yield an intermediate result of type ptrdiff_t, which is then
converted to size_t. This may cause problems for very large types
and objects on some systems (though the overflow on the subtraction
and the overflow on the conversion may well cancel each other out,
yielding the correct answer anyway).

Finally, they're ugly.

(It's likely I've missed some cases.)

So yes, strictly speaking the sizeof operator is unnecessary.
If I had to work in a crippled language that's like C but with the
sizeof operator removed, I could work around the problem in most
cases by defining and using these macros.

Is that really what you had in mind? If so, why waste your time?
sizeof exists for a reason. Just use it.
 
K

Keith Thompson

Rod Pemberton said:
Keith Thompson said:
Rod Pemberton said:
news:p[email protected]... [...]
Standard Headers

There are a dozen or two of these, and you have to keep including or
unincluding them as the contents of the file change.

Why not just take the inclusion of all of them as read? (There are
all sorts of reasons why it's kept like this, but remember a
newcomer to the language doesn't care about these reasons, only that
they are a right pain.)

There is much code that doesn't use them and has functions with
identical names, etc. E.g., I frequently need one or two
string.h function(s). So, I implement them with the same name and
skip including string.h. You need stdio.h for file I/O. But,
who really needs ctype.h? stdlib.h? stdbool.h? You can write
equivalent code without them.

Why on Earth would you do that?

Portability. Completeness. Simplification. Optimization... Not all C
compilers, esp. older or C-subset, have complete libraries. If you're
working in a new environment, you might only be able to bootstrap an older C
or a C-subset compiler.

If you're working with a new and incomplete implementation, that
might make some sense as a *temporary* workaround. It probably
also makes sense if you're using a freestanding implementation,
a possibility we tend to ignore here.

But for hosted implementations, a complete library will almost
certainly be available. Unless you have a specific requirement to
support non-conforming implementations, writing code that allows
for the possibility of an incomplete library doesn't make more
sense than writing code that allows for the possiblity that 2+2
might yield something other than 4.

[...]
I guess no one else has ever passed values from a hash function into a
switch?

I don't think I ever have. I said "relatively rare", not nonexistent.
That works. It's not my first choice though. It just transposes the
locations where one must add additional control flow. E.g., "break;" is
removed, while, say, "fallthru;" is added. It's much like rewriting a loop
with "break's" to use "continue's" instead.

Except that "fallthrough;" (yes, I'd insist on spelling it correctly)
would be much rarer than "break;" is in current C code. Make the
normal case the default, and require a little extra work for the
exception. Of course it's too late to change this in C, unless we
leave the switch statement alone and add a new form of selection
statement (something I'm not advocating).

It also imposes an arbitrary ordering on the cases and restricts
which cases can fall through to which other cases. You can have
case X fall through to case Y, and Y to Z, but you can't have case
X perform just actions X and Y and case Y perform actions Y and Z.
Nor can you have both X and Y fall through to Z.

Fortunately, the language does have a mechanism that allows each
case to perform whatever arbitrary sequence of actions you like:
the function call. (And yes, that imposes its own restrictions.)

[...]
There are many old C and C-subset compilers that don't implement them.

I'm skeptical that there are *any* old C compilers that don't
implement enum that are in current active use. C-subset compilers
could be an issue, and if you're forced to work with them you're facing
a whole set of problems that most of us don't have to worry about.

So, what specific platforms have C-subset compilers but lack
conforming C compilers (conforming at least to K&R1 if not C90)?
Do you actually work with such a platform?
Even if you handle text...


If that's (non-ASCII charset support of text files) really needed, you can
write them ('\r' and '\n') out as text, read them back in as binary, emit
the read-in binary sequence instead of escapes. Portable... ASCII is still
dominant. The EBCDIC coders can fix up the common ASCII issues. They're
aware of the problems of C coded with ASCII. Of course, it's really not
wise to use huge charsets for character representation in source code...

So I can write simple code, using text mode, that quietly and
correctly handles whatever text file format is used on whatever system
is out there, while you use binary mode and handle the line endings
yourself, resulting in significantly more complex code that will break
as soon as it's ported to a system with a text format that you didn't
think of.

You can't even write a portable "hello world" program using binary
mode.
It's interesting that you didn't mention ctype.h functions. There is *much*
code that implements their own ASCII based ctype.h functions, e.g., ASCII
based isapha(), if ch>='a' || ch<='z' etc... Yet, a simple #define and use
of a string.h function (e.g., strchr) could've made the isalpha() etc. code
portable.

No, I didn't mention the ctype.h functions. They exist, they work,
they're portable. Are you suggesting that an ASCII-specific
ch>='a' || ch<='z' is *better* than the standard isalpha()?
Believe it or not, I recently ran into *old* code that used "static",
"double", and "register", as variables...

How old was it? "static", "double", and "register"
have been keywords in C for a *very* long time; see [Cman.pdf]

1980 or so. Yes, that's afterwards, but not that long afterwards (assuming
1974).

I'm skeptical. Specifically, I don't believe that there was a C
compiler (*not* a B or BCPL compiler) being used in 1980 in which
"static", "double", and "register" were not treated as keywords.
I've seen no evidence that there was *ever* a version of C in which
they aren't keywords. Can you provide evidence for your claim?
 
E

Erik Trulsson

In comp.lang.c.moderated jacob navia said:
Casey Hawthorne a écrit :

The compiler system lcc-win has tried to do exactly that, i.e. to
develop a cleaner version of C.

If that is what it has tried to do it has failed. Badly. It *may* have
succeeded in creating a better version of C, but not a cleaner one.
It introduces as enhancements, compatible with standard C, the following
features:

Just adding features, without removing or modifying any of the existing
features, will not make it cleaner. On the contrary it will make the
language more of a mess than it is.
 
R

Richard Delorme

Le 05/03/2010 18:56, Casey Hawthorne a écrit :
Peter Van Der Linden in "Expert C Programming - Deep C Secrets" 1994
and I imagine others have pointed out some of C's idiosyncrasies.
Has thought been given given to a cleaned up C? Possibly called C+.

While reading this thread, it looks that some people want to make
additions to the language, like Jacob Navia's operator overloading &
generic containers. To make the language simpler, or cleaner, why not
rather remove things from it. For example :

- void can be removed from the language. So instead of declaring
void f(void);
we can simply write :
f();
The generic pointer type (void *), could then be replaced by (char*)
without much harm.

- auto can be removed from the language.

- register can be removed from the language. The only thing it is
usefull is to prevent the usage of the address of a variable. If we do
not want to use an address of a variable I think we can refrain
ourselves from doing so, without the need of a keyword. Some compiler
can do some better optimizations with it, but I think most of recent
compilers don't really care of the presence of this keyword.

- restrict can be removed. It is mostly here to facilitate some
optimizations by the compiler by preventing aliases. I think this is not
the duty of the programmer to facilitate optimization, but rather the
burden of the compiler.

- -> operator can be replaced by the . operator.

We can also get further by cleaning the names of basic types. I would
prefer to spell char b.y.t.e., as it makes its purpose more obvious.
Some integer types are redundant, short/int or int/long or long/long
long depending on the machine. I think such redundancy should go.

Obviously the standard library could be improved, at least by removing
dangerous function like gets() or stupid functions like strncpy and
making all functions thread safe. It might also be made simpler by
removing useless type like size_t.
 
L

Lew Pitcher

On March 15, 2010 13:25, in comp.lang.c, (e-mail address removed) wrote:
[snip]
- -> operator can be replaced by the . operator.

This suggestion seems contrary to the pattern you establish with your other
suggestions. While your other suggestions address language simplification
for the programmer's benefit, this one complicates a programer's work

For me, it is simpler to write
a->b
than it is to write
(*a).b
K&R even refers to the -> notation as a "convenient shorthand".

For that matter, if you suggest eliminating the -> operator, then why not
also eliminate the [ ] subscript operator, in favour of the * operator;
after all,
a
is identical in operation and side-effects to
*(a+b)
and is also a "convenient shorthand" for the operation.
 
A

Andrew Poelstra

- -> operator can be replaced by the . operator.

I like this operator. The dot is a clear indicator
that you're working with a local struct and that as
soon as it goes out of scope your changes are gone.

But with -> you know to be a little more careful.
 
K

Keith Thompson

Richard Delorme said:
Le 05/03/2010 18:56, Casey Hawthorne a écrit :

While reading this thread, it looks that some people want to make
additions to the language, like Jacob Navia's operator overloading &
generic containers. To make the language simpler, or cleaner, why not
rather remove things from it.

Any such change will break existing code.
For example :

- void can be removed from the language. So instead of declaring
void f(void);
we can simply write :
f();

"f();" already has a meaning in C90; it declares f as a function
returning int and taking an unspecified but fixed number and type
of parameters. C99 dropped implicit int, but "f();" would still
be ambiguous at block scope; is it a function declaration or a
function call?
The generic pointer type (void *), could then be replaced by (char*)
without much harm.

Except that there would no longer be a way to distinguish between a
generic pointer and a pointer that actually points to character data.
- auto can be removed from the language.

Ok. (Note that C++ has recycled the "auto" keyword for another purpose.)
- register can be removed from the language. The only thing it is
usefull is to prevent the usage of the address of a variable. If we do
not want to use an address of a variable I think we can refrain
ourselves from doing so, without the need of a keyword. Some compiler
can do some better optimizations with it, but I think most of recent
compilers don't really care of the presence of this keyword.

That's probably ok, though I'm sure some would disagree. Of course
it would break existing code, but deleting the "register" keyword
for such code would avoid that.
- restrict can be removed. It is mostly here to facilitate some
optimizations by the compiler by preventing aliases. I think this is
not the duty of the programmer to facilitate optimization, but rather
the burden of the compiler.

The restrict keyword is intended to facilitate optimization in cases
where the compiler doesn't have enough information.
- -> operator can be replaced by the . operator.

Maybe, but I'm not sure that having two distinct meanings for
a single operator is a simplification.
We can also get further by cleaning the names of basic types. I would
prefer to spell char b.y.t.e., as it makes its purpose more
obvious.

I wouldn't mind having "byte" as a fundamental type, but what about
actual character data?
Some integer types are redundant, short/int or int/long or
long/long long depending on the machine. I think such redundancy
should go.

What about a system with 8-bit char, 16-bit short, 32-bit int,
64-bit long, and 128-bit long long? I don't know whether such
systems currently exist, but they easily could.

One possibility would be to drop long long and support additional
types as extended integer types, with appropriate typedefs in
Obviously the standard library could be improved, at least by removing
dangerous function like gets() or stupid functions like strncpy and
making all functions thread safe.

gets() is already being deprecated in C201X.

I wouldn't mind dropping strncpy(), but there is *some* code that uses
it. Likely most of that code really should be using something else
instead, but I'm sure some fraction of it actually needs it. Of
course it's easy enough to reimplement.
It might also be made simpler by
removing useless type like size_t.

Useless?? What would you use instead?
 
K

Keith Thompson

jacob navia said:
Richard Delorme a écrit : [...]
We can also get further by cleaning the names of basic types. I
would prefer to spell char b.y.t.e., as it makes its purpose more
obvious. Some integer types are redundant, short/int or int/long or
long/long long depending on the machine. I think such redundancy
should go.

Obviously the standard library could be improved, at least by
removing dangerous function like gets() or stupid functions like
strncpy and making all functions thread safe. It might also be made
simpler by removing useless type like size_t.
This is already in the future standard. Most functions of the Microsoft
safe library proposal are accepted in the standard library.

Are they? I don't see them in N1425. N1135 is titled "Specification
for Safer, More Secure C Library Functions", and appears to contain
what you're talking about, but I'm not sure of its status; does the
committee intend to add these functions to the standard library,
or are then an optional addendum?
 
K

Keith Thompson

Richard Delorme said:
Obviously the standard library could be improved, at least by removing
dangerous function like gets() or stupid functions like strncpy and
making all functions thread safe.
[...]

This requires defining what "thread safe" means. C201x does add
threading, but that's hardly consistent with making the standard
library smaller.

At least in some cases, it might make more sense to add thread-safe
versions of some library functions, leaving the existing thread-unsafe
versions in place. (I'm thinking that there could be a performance
impact, but I could be wrong.)
 
I

Ian Collins

Richard Delorme said:
Obviously the standard library could be improved, at least by removing
dangerous function like gets() or stupid functions like strncpy and
making all functions thread safe.
[...]

This requires defining what "thread safe" means. C201x does add
threading, but that's hardly consistent with making the standard
library smaller.

At least in some cases, it might make more sense to add thread-safe
versions of some library functions, leaving the existing thread-unsafe
versions in place. (I'm thinking that there could be a performance
impact, but I could be wrong.)

Which is the approach adopted by Posix with the suffix "-r" for
reentrant functions.
 
R

Richard Delorme

Le 15/03/2010 21:33, Keith Thompson a écrit :
Any such change will break existing code.

I do not agree with this point of view. First, a new language version
does not mean the end of all previous versions. The same compiler can
target K&R C, C90, C99 with the right option. Secondly, it is possible
to smoothly deprecate old parts of a language before removing them. A
diagnostic message warning about the deprecated construct may be used
for a while for a still supported feature.

"f();" already has a meaning in C90; it declares f as a function
returning int and taking an unspecified but fixed number and type
of parameters.

Which is a pretty useless declaration.
C99 dropped implicit int, but "f();" would still
be ambiguous at block scope; is it a function declaration or a
function call?

Forward function declaration should be added to my list of things to remove.
Except that there would no longer be a way to distinguish between a
generic pointer and a pointer that actually points to character data.

Right. Is this really a problem ? Maybe a byte type instead of the char
type will make things easier.
The restrict keyword is intended to facilitate optimization in cases
where the compiler doesn't have enough information.

Or when the compiler is not clever enough. But I am not sure a typical C
programmer will be able to provide this information better than a compiler.
Maybe, but I'm not sure that having two distinct meanings for
a single operator is a simplification.

Nor I am. But are the two meanings so distinct? An advantage of using a
single operator is in case of refactoring some code, replacing object
type with pointer to object will then be much easier.
I wouldn't mind having "byte" as a fundamental type, but what about
actual character data?

Having a byte type will free the char type to actually represent
characters, and only characters.
What about a system with 8-bit char, 16-bit short, 32-bit int,
64-bit long, and 128-bit long long? I don't know whether such
systems currently exist, but they easily could.

In such a system, there is no redundancy, so I have no objection here. I
was writing about the other cases.

Useless?? What would you use instead?

The type it is typedef from.
 
R

Richard Delorme

Le 15/03/2010 22:22, Keith Thompson a écrit :
Richard Delorme said:
Obviously the standard library could be improved, at least by removing
dangerous function like gets() or stupid functions like strncpy and
making all functions thread safe.
[...]

This requires defining what "thread safe" means.

Sorry, I meant reentrant. Reentrancy problems, although exacerbated in
multi-threaded programs, can arise on single-threaded programs. For
example the POSIX function strtok_r is a reentrant version of of strtok.
 
B

Bart

The restrict keyword is intended to facilitate optimization in cases
where the compiler doesn't have enough information.

All these keywords are very worthy but they do clutter things up.
I wouldn't mind having "byte" as a fundamental type, but what about
actual character data?

What about both? A char type (always unsigned), and a signed/unsigned
byte for integer values.
What about a system with 8-bit char, 16-bit short, 32-bit int,
64-bit long, and 128-bit long long?  I don't know whether such
systems currently exist, but they easily could.

C#'s type system, based exactly on 8,16,32 and 64-bit values, seems
wonderfully clear and concise. You always know exactly what width you
will get.

But C# doesn't have to run on weird hardware so C can't really join in
the fun, it's stuck with it's snazzy looking int_least32_t and
friends.
 
B

Ben Bacarisse

Lew Pitcher said:
On March 15, 2010 13:25, in comp.lang.c, (e-mail address removed) wrote:
[snip]
- -> operator can be replaced by the . operator.

This suggestion seems contrary to the pattern you establish with your other
suggestions. While your other suggestions address language simplification
for the programmer's benefit, this one complicates a programer's work

For me, it is simpler to write
a->b
than it is to write
(*a).b
K&R even refers to the -> notation as a "convenient shorthand".

I think the proposal is to use . in place of ->. The compiler can
always tell whether the LHS is a pointer or a struct, so it always
know what to do with E1.E2.

<snip>
 
I

Ian Collins

Le 15/03/2010 21:33, Keith Thompson a écrit :

The type it is typedef from.

Well that depends on the environment (32/64 bit etc.), so there would
have to be a typedef.

So what do you propose changing? Going from a standard typedef to an
arbitrary one?
 
I

Ian Collins

Ian Collins said:
On 03/16/10 10:22 AM, Keith Thompson wrote: [...]
At least in some cases, it might make more sense to add thread-safe
versions of some library functions, leaving the existing thread-unsafe
versions in place. (I'm thinking that there could be a performance
impact, but I could be wrong.)

Which is the approach adopted by Posix with the suffix "-r" for
reentrant functions.

You mean "_r", yes?

Yes!
 
K

Keith Thompson

Richard Delorme said:
Le 15/03/2010 21:33, Keith Thompson a écrit :

I do not agree with this point of view. First, a new language version
does not mean the end of all previous versions. The same compiler can
target K&R C, C90, C99 with the right option. Secondly, it is possible
to smoothly deprecate old parts of a language before removing them. A
diagnostic message warning about the deprecated construct may be used
for a while for a still supported feature.
Ok.


Which is a pretty useless declaration.

Perhaps, but any change that silently changes the meaning of existing
code is suspect.
Forward function declaration should be added to my list of things to remove.

What exactly do you mean by "Forward function declaration"? If you
mean that you want to drop the ability to declare a function at block
scope, I might not disagree (thought that might cause problems if
we ever want to introduce nested function *definitions*).
Right. Is this really a problem ? Maybe a byte type instead of the
char type will make things easier.

Here you imply that type byte replaces type char; see belo.
Or when the compiler is not clever enough. But I am not sure a typical
C programmer will be able to provide this information better than a
compiler.

A typical C programmer might not, but it's used in the declarations of
a number of functions in the standard library.

"restrict" is useful in cases where no compiler, no matter how clever,
can gather enough information to enable an optimization (unless some
of the optimization is done at link time, but I don't think we want to
require that).
Nor I am. But are the two meanings so distinct? An advantage of using
a single operator is in case of refactoring some code, replacing
object type with pointer to object will then be much easier.

I wouldn't have a major problem with that, apart from the obvious one
of breaking most existing C code. But a lot of C programmers
actually like the fact that "." and "->" are distinct symbols.
Having a byte type will free the char type to actually represent
characters, and only characters.

.... And now you imply that byte is a new type, and char will continue
to be supported.

If you want to break the guarantee that sizeof(char)==1, I don't think
that's going to fly; too much code depends on it, and I don't think it
could be corrected by an automated tool. If not, what's the
difference between "byte" and "char"? Are they the same type? Are
they distinct types with the same representation? Is byte signed
or unsigned? Can you write "unsigned byte" and "signed byte"?

I can see the point of using the name "byte" rather than "char" for
documentation purposes, but "typedef unsigned char byte;" can already
do that.
In such a system, there is no redundancy, so I have no objection
here. I was writing about the other cases.

You're talking about making changes to the language. Would "long
long" be a predefined type on the hypothetical system I mentioned,
and nonexistent on other systems? Ick.
The type it is typedef from.

And how am I supposed to know which type that is? How do you expect
me to write portable code?
 
J

James Kuyper

Richard said:
Le 05/03/2010 18:56, Casey Hawthorne a �crit :

While reading this thread, it looks that some people want to make
additions to the language, like Jacob Navia's operator overloading &
generic containers. To make the language simpler, or cleaner, why not
rather remove things from it. For example :

It is, quite properly, very much more difficult to remove things from a
well-established language standard than it is to add them. Existing code
is important, so backwards compatibility is also important. Every time
someone argues that it's a simple matter to automatically update the
code to a new standard, you should ask them "Are you willing to
reimburse me the costs associated with testing several million lines of
code to make sure the automatic fix didn't damage anything?"

Creating a new language that doesn't have to worry about backwards
compatibility is much more appropriate than making
backwards-incompatible changes to the existing language.
- void can be removed from the language. So instead of declaring
void f(void);
we can simply write :
f();
The generic pointer type (void *), could then be replaced by (char*)
without much harm.

Using 'void' to indicate "no return type" or "no arguments" was bad
design, necessitated by issues of backwards compatibility. I have no
objection to a new language where you can express those things by the
absence of a specified return type or the absence of specified arguments.

However, void* is an entirely different issue, and it was invented
precisely for features that char* does not and should not provide: most
importantly, implicit conversions to and from other pointer types. If
you remove that, I want a replacement, and it must not be char*; so why
bother changing the name?
- auto can be removed from the language.

No argument there - it's pointless, and always has been, making
backwards compatibility an almost completely irrelevant issue.
- register can be removed from the language. The only thing it is
usefull is to prevent the usage of the address of a variable. If we do
not want to use an address of a variable I think we can refrain
ourselves from doing so, without the need of a keyword. Some compiler
can do some better optimizations with it, but I think most of recent
compilers don't really care of the presence of this keyword.

The 'register' keyword could easily be rendered meaningless in C without
too much trouble; that would constitute standardizing existing practice.
However, removing it would be a problem because of existing code.
- restrict can be removed. It is mostly here to facilitate some
optimizations by the compiler by preventing aliases. I think this is not
the duty of the programmer to facilitate optimization, but rather the
burden of the compiler.

The restrict keyword gives the compiler permission to perform
optimizations that the compiler could not otherwise be certain were safe.
- -> operator can be replaced by the . operator.

Using the same operator for (*struct_pointer).member and
actual_struct.member hides the distinction between pointers and objects;
that strikes me as a dangerous idea. It's been pointed out that this in
analogous to the special handling that the standard specifies for
function and array types. While that's perfectly true, I'm not sure it's
an argument in favor of the idea. The automatic conversion of lvalues of
array types into pointers to the first element of the array is one of
the most common confusions among newbies. The special handling of
function pointers seems less confusing only because it doesn't come up
as often (in the code I've seen - YMMV).
We can also get further by cleaning the names of basic types. I would
prefer to spell char b.y.t.e., as it makes its purpose more obvious.
Some integer types are redundant, short/int or int/long or long/long
long depending on the machine. I think such redundancy should go.

As long as any concern is taken about backwards compatibility is
concerned, that's a complete impossibility.

There's no pair of types that are redundant on every platform, and
there's some platforms where each of the standard integer types has a
different size.

For a completely new language, I'd recommend a simplified version of the
size-named types, rather than worrying about fiddling around with the
old specially-named types. In particular, I'd recommend giving the
'fast' types simple names, and making the exact-sized types a longer
name, to discourage their use; exact-sized types are occasionally the
right choice, but much less often than people think they are.
Obviously the standard library could be improved, at least by removing
dangerous function like gets() or stupid functions like strncpy and
making all functions thread safe. It might also be made simpler by
removing useless type like size_t.

What would you use in place of size_t? Keep in mind that the target
platforms for C include machines with as little as 32K of memory, and
with no upper limit - are you going to mandate a one-size-fits-all
solution for implementations at both extremes in that range?
 
J

jacob navia

James Kuyper a écrit :
It is, quite properly, very much more difficult to remove things from a
well-established language standard than it is to add them. Existing code
is important, so backwards compatibility is also important. Every time
someone argues that it's a simple matter to automatically update the
code to a new standard, you should ask them "Are you willing to
reimburse me the costs associated with testing several million lines of
code to make sure the automatic fix didn't damage anything?"

Contrary to what Mr Delorme writes, I have (in this forum and in
comp.std.c) argued extensively AGAINST some "features" of the C library,
specifically gets() and asctime(). The committee has dropped those
functions from the language, what confirms that IT IS well possible to
drop things from C. It is surely a good decision from them.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
474,116
Messages
2,570,700
Members
47,277
Latest member
GYZMilton9

Latest Threads

Top