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

  • Thread starter Casey Hawthorne
  • Start date
R

Richard Delorme

Le 15/03/2010 21:32, jacob navia a écrit :
Richard Delorme a écrit :

This makes impossible to know if you forgot to type the return value
or you wanted to have a void function.

three() {
return 3;
}

Isn't it clear than in the above function I forgot the return type ?
Then, you can't know if you are dereferencing a void * by mistake!

Under the hypothesis that void is no more part of the language, I do not
understand your remark.
lcc-win honors the register directive...

How ? Just by forbidding the usage of the address of the variable, or by
actually assigning the variable to a true register ?

It is useful for remembering to avoid aliasing an address

For the programmer ? I guess a good programmer looking for some
performance will always avoid aliasing.
Maybe, but I find it clearer as it is now. You know that at the left
side of the name is a pointer, not an object.

My code uses a lot of -> and I find it makes the code harder to read
than a single dot.
 
I

Ian Collins

James Kuyper a écrit :

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.

I didn't think they had dropped asctime().

Removing dodgy functions from the standard library is way easier in
practice than removing things from the core language. If you have an
investment in code that uses gets(), you can add your own.
 
J

Jasen Betts

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 :

- 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.

strncpy is not stupid, it's just often misused, fgets is also often
misused, should that be aboloshed too.

I think I have used strncpy exactly twice where its behavior was
exactly what I wanted, without it I would have had to find some other
way, perhaps using memcpy.

null padded fixed length buffers seem to have gone out of style.


--- news://freenews.netfront.net/ - complaints: (e-mail address removed) ---
 
W

Willem

Bartc wrote:
) Keith Thompson wrote:
)> 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*).
)
) That's not going to happen (and if it does, I don't see how it affects this
) point).
)
) The problem at the minute is that if you define main() f() g() h() then you
) have to declare f() g() h() first, if they are used by main() for example.
) So you either duplicate parameter lists, or have to use a possibly unnatural
) f() g() h() main() order.

But then how can you...

Oh wait! You want to make it so that a function declaration is valid
for the whole file, and not just the bit downward from the declaration.
I couldn't agree more!

But you still want to be able to put declarations in header files, don't
you ? Or do you want to do that differently as well ?

I recall a discussion we had earlier about a new type of 'include' (I think
we called it 'import') which reads another C file and parses it for
function declarations and possibly some other stuff.

Most of this can be done in such a way as to not break existing code,
especially if you mandate warnings for all the 'removed' stuff.


SaSW, Willem
--
Disclaimer: I am in no way responsible for any of the statements
made in the above text. For all I know I might be
drugged or something..
No I'm not paranoid. You all think I'm paranoid, don't you !
#EOT
 
R

Rod Pemberton

Keith Thompson said:
Rod Pemberton said:
Keith Thompson said:
[...]
If I were
redesigning the switch statement from scratch, you'd be able to
specify multiple values in a single case, the "break" keyword
would not be required, and there would probably be special syntax
to specify falling through to the next case.

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.

What about "recase" or "reswitch"? E.g., perhaps like so:

case 0x10: recase (0x30);
case 0x20: /* stuff */
break;
case 0x30: /* stuff */
break;

The advantage is you don't need a goto label. The ordering can be as one
wishes. And, each case could then be auto-break. Hmm, that's not too bad,
IMO.
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?

Well, you'd accept that they are C-subset compilers... since they don't
have those keywords. But, they're still C compilers.

Ron Cain's SmallC and variants
(1980, PC, no auto, static, extern, register, double, or float)

Lutz Hamel's WCC
(1987, VMS, no auto, static, extern, register, or double, has float)

You can't even write a portable "hello world" program using binary
mode.

Sigh.. Ok, you never post code. You could've done so to demonstrate
whatever you're getting at. But, you always want others to do so, so that
you can pick their's apart. Fine, here's one of many possible "Hello
World!" programs in C:


#include <stdio.h>
#include <stdlib.h>

#define HW "Hello World!\n"

int main(void)
{
FILE *out;
char ch;

out=tmpfile(); /* ANSI wb+ */
fprintf(out,HW);
rewind(out);
while(1)
{
ch=getc(out);
if(feof(out))
break;
putchar(ch);
} /* because I could... */

exit(EXIT_SUCCESS);
}


The code works for MS-DOS with multiple compilers (ASCII CRLF as newline).
It works for 64-bit Linux with GCC (ASCII LF as newline). I can't test
MAC's (non-x86 Mac's had ASCII CR as newline), nor EBCDIC (EBCDIC NL as
newline), nor DEC VMS. I seem to recall DEC VMS used a wierd escape
sequence for newline. But, DEC VMS is supposed to use the MCS (VT-220)
charset from which ISO-8859-1 was derived. The first 127 char's of
ISO-8859-1 are ASCII. In which case, the charset shouldn't be an issue.
Feel free to test those and other systems, like Stratus, Tandem, Cray,
PDP-11, or whatever...


If you want to test EBCDIC and only have an x86 PC, you could try this IBM
emulation (I've not done so.):

http://mvs380.sourceforge.net/
http://gccmvs.sourceforge.net/

... portable ...

C'mon? Who cares? Really! C is only *so* portable anyway (30% IMO).
Personally, I only have need of C programs working for ASCII, x86, DOS,
Linux.

(I.e., why do I or anyone else for that matter care if it's portable if it
works on an x86 PC? It's the _dominant_ computing platform. I don't have
access to IBM systems or mainframes. I no longer have access to
miniframes, or VMS. So, I can't test the code on them, nor can I fix found
issues. Most other people don't have access either. So, if the compiler
warnings don't catch it, then it's "portable"...)


Rod Pemberton
 
W

Willem

Rod Pemberton wrote:
) What about "recase" or "reswitch"? E.g., perhaps like so:
)
) case 0x10: recase (0x30);
) case 0x20: /* stuff */
) break;
) case 0x30: /* stuff */
) break;
)
) The advantage is you don't need a goto label. The ordering can be as one
) wishes. And, each case could then be auto-break. Hmm, that's not too bad,
) IMO.

I would prefer the 'see' keyword, and I would then recommend pointing back
to earlier cases: It

case 0x10: /* stuff */
break; /*
case 0x20: /* Other stuff */
break;
case 0x30: see case 0x10;

Oh come on, it's too funny not to do it :p



SaSW, Willem
--
Disclaimer: I am in no way responsible for any of the statements
made in the above text. For all I know I might be
drugged or something..
No I'm not paranoid. You all think I'm paranoid, don't you !
#EOT
 
J

jameskuyper

Rod said:
Sigh.. Ok, you never post code. You could've done so to demonstrate
whatever you're getting at. But, you always want others to do so, so that
you can pick their's apart. Fine, here's one of many possible "Hello
World!" programs in C:


#include <stdio.h>
#include <stdlib.h>

#define HW "Hello World!\n"

int main(void)
{
FILE *out;
char ch;

out=tmpfile(); /* ANSI wb+ */
fprintf(out,HW);
rewind(out);
while(1)
{
ch=getc(out);
if(feof(out))
break;
putchar(ch);
} /* because I could... */

exit(EXIT_SUCCESS);
}


The code works for MS-DOS with multiple compilers (ASCII CRLF as newline).
It works for 64-bit Linux with GCC (ASCII LF as newline). I can't test
MAC's (non-x86 Mac's had ASCII CR as newline), nor EBCDIC (EBCDIC NL as
newline), nor DEC VMS. I seem to recall DEC VMS used a wierd escape
sequence for newline. But, DEC VMS is supposed to use the MCS (VT-220)
charset from which ISO-8859-1 was derived. The first 127 char's of
ISO-8859-1 are ASCII. In which case, the charset shouldn't be an issue.
Feel free to test those and other systems, like Stratus, Tandem, Cray,
PDP-11, or whatever...

stdout is a text stream; how does your program qualify as a counter-
example? Sure, your program does use a binary mode stream for an
intermediate step, but if your system creates an actual file
corresponding to that stream, you'll find that it's lines are not
correctly terminated on most of the platforms you listed above. The
only file containing correctly terminated lines on each of those
platforms is the one created by writing to a text stream.

The proposal he was arguing against would do away with text mode
streams, which would make stdout a binary stream, and your program
would fail miserably on most of those platforms if that change were
implemented on them.

....
C'mon? Who cares? Really! C is only *so* portable anyway (30% IMO).

I have no idea what the numerator and denominator you're thinking of
for that %age. If the numerator is the total number of clock cycles
executed per day by platforms that are permitted targets for compilers
that conform fully to at least one version of the C standard, and the
denominator is the total number of clock cycles executed per day by
all programmable platforms, I think you'll find the percentage a LOT
higher than 30%; I'd guess it's at least 90%, and possibly larger than
99%.
Personally, I only have need of C programs working for ASCII, x86, DOS,
Linux.

The fact that you have limited portability needs doesn't mean that
everyone else's needs are similarly parochial.
 
J

Jasen Betts

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 :

- 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.

strncpy is not stupid, it's just often misused, fgets is also often
misused, should that be aboloshed too.

I think I have used strncpy exactly twice where its behavior was
exactly what I wanted, without it I would have had to find some other
way, perhaps using memcpy.

null padded fixed length buffers seem to have gone out of style.


--- news://freenews.netfront.net/ - complaints: (e-mail address removed) ---
 
N

Nick Keighley

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.


Just adding features, without removing or modifying any of the existing
features, will not make it cleaner.

A designer knows he has achieved perfection
not when there is nothing left to add,
but when there is nothing left to take away.
Antoine de Saint-Exupéry

 On the contrary it will make the
language more of a mess than it is.

this kind of assumes it *is* a mess.

I think if Jacob tried to do the kind of radical surgery that you'd
probably like he'd find his proposals even less acceptable. There's
always Java or C# for those that want Radical-C.
 
N

Nick Keighley

Any such change will break existing code.

well, yes but this is a cleanup and simplification

"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.  

and what do you need that for? Backward compatibility with K&R C? C++
seem to manage to drop void in these circumstances without a problem.
C99 dropped implicit int, but "f();" would still
be ambiguous at block scope; is it a function declaration or a
function call?

without a return type it's a call.

Except that there would no longer be a way to distinguish between a
generic pointer and a pointer that actually points to character data.


Ok.  (Note that C++ has recycled the "auto" keyword for another purpose..)

not one of their smarter moves

Maybe, but I'm not sure that having two distinct meanings for
a single operator is a simplification.

this being completely unprecedented in the C language

i = i * 2;
f = f * 2.0;
t = *tp;

octet is cleaner and less ambiguous
I wouldn't mind having "byte" as a fundamental type, but what about
actual character data?

and they could be proper unicode characters

<snip>
 
N

Nick Keighley

On 03/16/10 12:24 PM, Richard Delorme wrote:

Why?

how?!

How would mutual recursion work? Or separate compilation? What about
those weird people who put main() at the beginning of their
compilation units?
 
J

Jasen Betts

Forward function declaration should be added to my list of things to remove.

you're kidding right?

what are you intending to use instead?

// bar.c

void bar(void)
{
foo( 3);
}

// foo.c

void foo( double x)
{
printf ("%lf",x);
}

without forward declarations how is the compiler to deal with that?


--- news://freenews.netfront.net/ - complaints: (e-mail address removed) ---
 
M

Michael Foukarakis

I don't entirely agree.  Obviously, both can be used securely,

This is the one side of the coin. In practice, all [str|mem]cpy and
friends can be used securely.
but in
practice, I think strlcpy() is easier to use in a reliably safe way.

This is the other side of the usability vs security tradeoff. Since
strlcpy() imposes an additional precondition (on size) which strncpy()
does not, and has no way to verify it, it doesn't offer anything in
security terms. It may be easier to use (turning that two-line
"strncpy and NUL terminate" into one) but it is meaningless from a
security point of view.
 
R

Richard Bos

jacob navia said:
Richard Delorme a =E9crit :
This is already in the future standard. Most functions of the Microsoft
safe library proposal are accepted in the standard library.

Oh, lord, I hope not. Replacing a mild gap with an inordinate crock is
_not_ an improvement, no matter what Mickeysoft fans may say.

Richard
 
R

Richard Bos

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".

No, _replace_, not dump and ignore.

It's as if there had been a ->() operator for function pointers. Then,
when you wanted to call a function through a pointer, you'd have the
choice between using
(*pointer)(args);
and
pointer->(args);
Except that, in ISO C, we can actually write
pointer(args);
since there is nothing else useful you _could_ do with the pointer at
that point, except call the function it points at.

Similarly, if we have a struct pointer, we can _now_ either do
(*pointer).member
or
pointer->member
but the proposal is that we could also do
pointer.member
since, exactly analogously to the function pointer case, there is
nothing reasonable you can do with a struct pointer and a member
operator except get the member of the struct pointed at.

It's not a new suggestion, by the way. It has been made many times
before. Personally, I'm not all that sure that I do like it, but I can
see the reasoning behind it.
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.


Because that's not what is being suggested. The analogous suggestion in
this case would be to make a+b equal to a. In this case, it _doesn't_
work, since a+b already has a meaning.

Richard
 
J

James Kuyper

Jasen Betts wrote:
....
I think I have used strncpy exactly twice where its behavior was
exactly what I wanted, without it I would have had to find some other
way, perhaps using memcpy.

null padded fixed length buffers seem to have gone out of style.

Not quite; most of the programs I'm responsible for work with such
buffers far more often than with variable length buffers.
 
R

Richard Bos

Richard Delorme said:
Le 15/03/2010 21:32, jacob navia a =E9crit :

three() {
return 3;
}

Isn't it clear than in the above function I forgot the return type ?

Yes. Now try this if all you have are a declaration and a precompiled
library.

Richard
 
A

Andrew Poelstra

strncpy is not stupid, it's just often misused, fgets is also often
misused, should that be aboloshed too.

How is fgets misused?
I think I have used strncpy exactly twice where its behavior was
exactly what I wanted, without it I would have had to find some other
way, perhaps using memcpy.

I think other people have similar stories about strncpy's usage -
and I think the effort it would take you to write your own (in 5 or
so lines, probably) would be justified by the pain saved by taking
it out of the language.
 
D

Daniel Giaimo

you're kidding right?

what are you intending to use instead?

// bar.c

void bar(void)
{
foo( 3);
}

// foo.c

void foo( double x)
{
printf ("%lf",x);
}

without forward declarations how is the compiler to deal with that?

Not that I am advocating the change, but Java has been dealing with such
things since the beginning. I fail to see why it would be so difficult
for a "C" compiler to do the same.
 

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

No members online now.

Forum statistics

Threads
474,263
Messages
2,571,062
Members
48,769
Latest member
Clifft

Latest Threads

Top