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

  • Thread starter Casey Hawthorne
  • Start date
I

Ian Collins

jacob said:
Flash Gordon a écrit :
No. As you (may) know, you have to write extern "C" in C++

Er, so? Wrap the header in extern "C" {..} and away you go.
 
K

Keith Thompson

jacob navia said:
Flash Gordon a écrit :


No. As you (may) know, you have to write
extern "C"
in C++

If you replaced "No" by "Yes", I'd agree. Yes, you have to write
extern "C"; that's *how* the API is available to C++.

I'm sure you didn't mean to imply that typing extern "C" is too
difficult, but I can't figure out what point you were making.
Can you clarify?
 
J

jacob navia

Seebs a écrit :
You know what's an awesome feature in a programming language? An "eval"
operation, which interprets strings as code. Incredibly flexible and
powerful.

Do you think we should add eval() to C? I don't.


I do not think this is a fair representation of his argument.

Under lcc-win you can do:


typedef void (fnptr)(void);

fnptr fn;

fn = CompileString("int main(void)(printf("\hello\"); )");
fn();

and you get "hello"...

This is called a JIT (Just in Time Compiler). Lcc-win has a JIT version.

(snip advice)
I believe his argument is that he does not feel that adding A and B would
improve C. For instance, I don't think that adding operator overloading would
improve C. I think it would make C worse. One of the things I like about
C is the confidence that I know what it's doing. Operator overloading is
a great fit for an OO language, where I expect objects to have internal state
and define their own rules. It's a poor fit for a language where I
expect operations to map very closely onto machine instructions.

-s

You do operator overloading in c when you use an operator like
+ since the compiler will do all necessary conversions for you.

The only thing that operator overloading adds to the language is the possibility
for the USER to add itsb own numeric types. Besides, if you do not like that
feature, do not use it. The language stays the same otherwise.

And (you probably know that)

unsigned long a,b,c;

// ...
c = a+b;

This translates into a function call in some machines.
(Specially 16 bit machines).
 
S

Seebs

Under lcc-win you can do:

The existence of your eval-like feature doesn't make that a fair
representation of his argument.
The only thing that operator overloading adds to the language is the possibility
for the USER to add itsb own numeric types. Besides, if you do not like that
feature, do not use it. The language stays the same otherwise.

If programs were written and maintained by a single person, sure.

But if you're looking at a few megabytes of code, the last thing you want
is to have the possibility that someone silently overloaded an operator.
unsigned long a,b,c;

// ...
c = a+b;

This translates into a function call in some machines.
(Specially 16 bit machines).

It may, or may not, but at least its behavior is fully understood. It's
not going to do something totally unlike addition.

-s
 
F

Flash Gordon

jacob said:
Flash Gordon a écrit :


No. As you (may) know, you have to write
extern "C"
in C++

Which means yes it is available to me, since I'm quite capable of doing
that.
That's a viewpoint. Another viewpoint (mine) is that experience has told
me NOT to use any widget set but use the API. This way, I have been able
to run programs written under windows 16 bits
today under windows 64 bits.

So? I'm able to run programs which started life in DOS using a text mode
widget set under 64 bit Linux, and if I tried I could get them to run
under 64 bit Windows as well. You just have to pick a widget set which
will continue to be supported because it is popular and good enough.

A decent Widget set can also deal with some of the portability issues,
assuming you pick one which is sufficiently ported.

Oh, and MS does eventually drop support for obsolete interface.
 
B

bartc

Richard Heathfield said:
bartc wrote:
Which is an alternative to writing (with some help from cdecl):

int (*x[10])(const char *);
Yes.

The typedefs at least turn it from impossible to possible, although in my
scheme, it would just be:

[10]*function(* const char)int x;

EEK!

That's supposed to be my reaction to the C equivalent...

My version actually is based on Algol-68 syntax, something like this I
believe, without 'const' attribute:

[10]ref proc(ref char)int x;

I changed 'ref' to '*' in order to be more C-friendly, obviously that didn't
work...
 
B

Ben Bacarisse

bartc said:
The typedefs at least turn it from impossible to possible, although in my
scheme, it would just be:

[10]*function(* const char)int x;

It doesn't *look* that different, but I managed to write it in a few seconds
from your description above, and anyone can understand it by reading from
left to right.

I think the word "function" is redundant in your scheme. Just as []s
announce an array, ()s announce a function. If you are concerned
about readability then "[]" could become "array []" and "*" could be
"pointer to" but if you are happy with minimal syntax elsewhere in the
scheme I'd suggest it for functions too.

<snip>
 
D

Dennis \(Icarus\)

jacob navia said:
Flash Gordon a écrit :


No. As you (may) know, you have to write
extern "C"
in C++

Which I'm pretty sure makes it accessible, and hence usable, to C++
programs,
:)
<snip>

Dennis
 
M

Michael Foukarakis

What does it means "GUI-intensive" and why should java be better at
solving these kinds of problems? Excluding subjective aesthetic
consideration on the resulting GUIs, I think some operations
"could" (but I'm unaware of recent changes so I could be wrong) be a bit
slower than an analogous C or C++ counterpart. Of course if maximum
speed is not required that's ok. A slow menu is not that cool btw...

Java was never that slow anyway, and with good JIT compilers its
performance is even closer to native code. I'm sure you can google
plenty of sources online that document this.
 
N

Nick

jacob navia said:
Seebs a écrit :

Under lcc-win you can do:


typedef void (fnptr)(void);

fnptr fn;

fn = CompileString("int main(void)(printf("\hello\"); )");
fn();

and you get "hello"...

This is called a JIT (Just in Time Compiler). Lcc-win has a JIT
version.

Can you do:

typedef void (fnptr)(void);

void tt(const char *msg) {
char fnbuff[1000];
fnptr fn;
snprintf(fnbuff,1000,"int main(void)(printf(\"%s\"); )");
fn = CompileString(fnbuff);
fn();
}

?

Because, if so, aren't you shipping the compiler around with the
executable. What if the code to be compiled relies on a library that
isn't on the target machine? And if not, what does it give you apart
from losing a static function (or, I admit, a group of closely related
static functions all with the same boilerplate).
The only thing that operator overloading adds to the language is the possibility
for the USER to add itsb own numeric types. Besides, if you do not like that
feature, do not use it. The language stays the same otherwise.

The danger with operator overloading is that it lets the USER add their
own NON NUMERIC [I thought I'd try adopting your STYLE for a while, but
got out of BREATH fairly QUICKLY] types. Look how long it took C++ to
get << and >> for streams - about 10 seconds.

The thing is though, this thread started by asking about what was got
wrong when C was designed. You immediately jumped in telling us about
what you've added to it. I think the intent of the question was what is
wrong with the underlying design.

Well I'd start with the inconsistencies in the standard library.
Half the functions that send things to a file take the file pointer as
the first argument. The other half take it as the last. puts is /not/
fputs defaulting to stdout.

By now these quirks are all second nature to me, but they are deeply
ugly and very confusing to newcomers.

Then I'd move on to the use of break inside both loops and switches -
leading to the behaviour of one of break/continue changing when you
embed a loop inside a switch clause but not the other.
 
P

Phred Phungus

jacob said:
Ian Collins a écrit :

Because the C standards committee has always decided NOT to add such
an improvement to the language. The C++ standard committee decided that
such an improvement WAS NECESSARY, and they develop one.

I have written most of the STL clone (AVL trees, RB trees, bitstrings,
flexible arrays, lists (double/single linked) and the whole library
is extremely fast and compact. It is just less than 100K when you use
all of it. If you use just the lists module it is less than 5K.

But apparently all this work is a waste of time. The committee decided
a feature freeze already, and I will not be ready to present this to
the next meeting in April.

Jacob,

Do you a link for this source?
 
P

Phred Phungus

Richard said:
Casey said:
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+.

According to Stroustrup [TC++PL, intro], the name "C+" has already been
taken, by a language unrelated to either C or C++.

I guessed the next one was going to be C flat.
 
N

Nick Keighley

If you replaced "No" by "Yes", I'd agree.  Yes, you have to write
extern "C"; that's *how* the API is available to C++.

I'm sure you didn't mean to imply that typing extern "C" is too
difficult, but I can't figure out what point you were making.
Can you clarify?


"C's magic low level abilities allow us to do things no other language
can achieve"
 
J

jacob navia

Nick Keighley a écrit :
"C's magic low level abilities allow us to do things no other language
can achieve"

For instance:

A full blown IDE under 1MB

A fast floating point package with 352 bits precision, in C+asm. The
core in assembler, the full C math library plus many other
special functions in C. Size: 204K.

I like C. The problem with modern softawre is BLOAT. Too much
features you do not need, too much inefficiency, the
contrary of "small is beautiful".

Well, I guess its a philosophical question anyway.
 
I

Ian Collins

jacob said:
Nick Keighley a écrit :

For instance:

A full blown IDE under 1MB

A fast floating point package with 352 bits precision, in C+asm. The
core in assembler, the full C math library plus many other
special functions in C. Size: 204K.

I like C. The problem with modern softawre is BLOAT. Too much
features you do not need, too much inefficiency, the
contrary of "small is beautiful".

Well, I guess its a philosophical question anyway.

The complexity of any given solution has to exist somewhere. It can
either be in the developer's code, or in the compiler writers.
 
N

Nick Keighley

bartc wrote:
And the typedef statement itself, which instead of having the type-spec
on one side, and the alias for it on the other, is all mixed up:
typedef int tenvector[10];
the typedef name is in the middle of the type-spec!

That's actually irrelevant - the typedef is remarkably easy to use.

yeah right...

To
define a synonym for an existing type, all you have to do is pretend
you're defining an object of that type, and stick typedef on the front.

so that defining a typedef is ***just as hard as*** defining an object

Let's say you want a synonym for an array of ten pointers to function
taking const char * and returning int.

the fact that you started with a readable english specification gives
a hint that there might be a better way.

Start simple:

int func(const char *);

That isn't actually what we want, but it's the first step. Now let's
turn it into a type synonym definition:

s/int/typedef int/

gives us

typedef int func(const char *);

func is now a type synonym. We use this in the next stage:

func arr[10];

Again, not quite what we want, so we:

s/func/typedef func/

to give

typedef func arr[10];

arr is now a synonym for "array of ten pointers to function taking const
char * and returning int".

It's hard to see how this could be made much simpler.

you missed the smiley!
 
N

Nick Keighley

bartc said:
Which is an alternative to writing (with some help from cdecl):
int (*x[10])(const char *);
The typedefs at least turn it from impossible to possible, although in my
scheme, it would just be:
[10]*function(* const char)int x;

That's supposed to be my reaction to the C equivalent...

My version actually is based on Algol-68 syntax, something like this I
believe, without 'const' attribute:

[10]ref proc(ref char)int x;

I changed 'ref' to '*' in order to be more C-friendly, obviously that didn't
work...

all programming languages are a subset of Algol-68
 
B

bartc

Ben Bacarisse said:
bartc said:
The typedefs at least turn it from impossible to possible, although in my
scheme, it would just be:

[10]*function(* const char)int x;

It doesn't *look* that different, but I managed to write it in a few
seconds
from your description above, and anyone can understand it by reading from
left to right.

I think the word "function" is redundant in your scheme. Just as []s
announce an array, ()s announce a function. If you are concerned
about readability then "[]" could become "array []" and "*" could be
"pointer to" but if you are happy with minimal syntax elsewhere in the
scheme I'd suggest it for functions too.

Although my proposal wasn't too serious (merely pointing out the merits of
left-to-right type-specifications), I think it is just about workable as it
is.

The main problem is recognising whether a "*" symbol starts an expression,
or a type-spec, which I think can be established by examining the next
symbol (if it's a typename, type attribute, "[" or "function", then it's
probably a type-spec).

Making "function" optional however makes "(" highly ambiguous: you can have
an unlimited run of "*" and "(" symbols, and not know until the end (if even
then) what you are parsing.

Function declarations would also be rendered practically invisible...
 
J

jacob navia

Nick a écrit :
jacob navia said:
Seebs a écrit :
Under lcc-win you can do:


typedef void (fnptr)(void);

fnptr fn;

fn = CompileString("int main(void)(printf("\hello\"); )");
fn();

and you get "hello"...

This is called a JIT (Just in Time Compiler). Lcc-win has a JIT
version.

Can you do:

typedef void (fnptr)(void);

void tt(const char *msg) {
char fnbuff[1000];
fnptr fn;
snprintf(fnbuff,1000,"int main(void)(printf(\"%s\"); )");

You have an error above The argument to printf is missing, and you get
an execution error. But I think I know what you mean. See later.
fn = CompileString(fnbuff);
fn();
}

?

Because, if so, aren't you shipping the compiler around with the
executable.

The compiler is called "CompileString" of course, and is a static
library you link with.

What if the code to be compiled relies on a library that
isn't on the target machine?

The JIT linker will surely complain and you will get NULL back.
You must tell the JIT where the dynamic libraries or static
libraries are. The JIT can load object files, shared objects
or static libraries.

And if not, what does it give you apart
from losing a static function (or, I admit, a group of closely related
static functions all with the same boilerplate).

The advantages of a JIT is that you can translate on the fly code
generated to fit certain circumstances that change from invocation to
invocation.


For instance a chemical company modelling molecules. The researcher
changes the high level model, they generate C from the model, and the
researches sees immediately the conserquences of his/her change
in the shape of the molecule displayed in the screen.

The only thing that operator overloading adds to the language is the possibility
for the USER to add itsb own numeric types. Besides, if you do not like that
feature, do not use it. The language stays the same otherwise.

The danger with operator overloading is that it lets the USER add their
own NON NUMERIC [I thought I'd try adopting your STYLE for a while, but
got out of BREATH fairly QUICKLY] types. Look how long it took C++ to
get << and >> for streams - about 10 seconds.

I am not convinced of any application of operator overloading that is not
(1) Done with new numeric types
(2) Done with access to containers (overloading [ ] )

ALl others, like using + to "add" srings or << or >> to print stuff are
bad usages in my opinion. Of course it can't be avoided. And, as you
know, in C I can write:

int AddTwoIntegers(int a,int b)
{
return a/b;
}

You can write bad code in ANY language.

The thing is though, this thread started by asking about what was got
wrong when C was designed. You immediately jumped in telling us about
what you've added to it. I think the intent of the question was what is
wrong with the underlying design.

Excuse me but the subject of this thread is:

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

Well I'd start with the inconsistencies in the standard library.
Half the functions that send things to a file take the file pointer as
the first argument. The other half take it as the last. puts is /not/
fputs defaulting to stdout.

By now these quirks are all second nature to me, but they are deeply
ugly and very confusing to newcomers.

Then I'd move on to the use of break inside both loops and switches -
leading to the behaviour of one of break/continue changing when you
embed a loop inside a switch clause but not the other.

Those are minor incoveniences. Yes, they are bad for newcomers but
what is essential is the stuff that is bad for newcomers AND for
experienced users.

Mr Heathfield is an experienced C programmer. The fact that even he had
a bug with zero terminated strings makes obvious that it is NOT his
abilities as a programmer that are bad, but a tool that uses ERROR PRONE
construct. (If you do not like my STYLE, please tell me how to put
emphasis in *plain ascii* :) )
 
N

Nick Keighley

jacob said:
Thomas Richter a crit :
Nobody is proposing that. This is an old trick in this discussions. Any
improvement to C is impossible because the old code. That is plainly not
true. The old code and the associated functions can be kept, but C
should be able to use BUFFERS of KNOWN length, avoiding the most common
cause of buffer overflows. Let's be explicit:
typedef struct {size_t length; char data[];} Buffer;
memset can be done as "Memset", for instance like this
bool Memset(Buffer *dest, int char_val);
[...] Strcpy is just as trivial, but with a character
buffer.

There is already a secure version of strcpy, see below.

where? I hope you don't mean strncpy().

Then C is not the right tool for the job. As said below, there are other
languages that can help. If you want to use C, there are also secured
functions with buffer sizes that help. But even they won't prevent you
from shooting yourself into the foot. C has no means to prevent bad
pointers being dereferences, to give another example. If you want a
child-proof C, use Java - it does have all the features you seem to
miss. (And no, I've absolutely nothing against Java, no irony here.)

I've got some sympathy with both sides. C is a small, low level,
portable language. And this is its strong point. On the other hand
I've debugged too many (of other people's) linked lists to appreciate
a standard list library. The cool thing about C++ is the STL. On the
gripping hand I'm not sure a generic list/tree library can be written
for C and even more dubious that it will overcome C's intertia. I also
don't like the idea of C getting fat.

[no, I'm not on the Standards Commitee. I just drink their Kool Aid]

Of course I make mistakes, who wouldn't? And your point is? Again, if
"avoiding errors" is your concern, use another tool and make other
errors. Just that languages like java or C++ are neither the right tool
for *some* jobs.

sometimes we don't have the opportunity to mix and match languages at
will. If we have a body of C code we can't usually add a Lisp module
just because we want a linked list.

A lot of this repeats so... said:
boring...




Then where is the damn problem?

Jacob was being sarcastic

Then keep it simple. If writing a list or a tree is not simple for you,
you are in the wrong field for applying C for that task.

what?! Just because something is reasonably straightforward doesn't
mean it should be done over and over again. Isn't the essence of
programming the packaging of ideas?
Or look for a
library that helps you. C is a small language; why whould that stuff be
required in the language core - it would often not fit into the
application because C doesn't have all the mechanisms of higher
languages to hide the implementation behind the design.

I have a this feeling too

It's obvious that you want to use C just for the means of it. Get over
it, C is not the "saves all my problems" language. It is good in some
cases, and bad in others. String manipulation and generic container
support are not the strong parts of C, so why force it? If you want to
make C another language, I again ask why. There *are* already other
languages in first place you can use.

I think Jocob wants something that is "better" than C (and a bit
bigger) but not as monstrous as C++. I'm curious as to whether he can
do it.


--
After a couple of projects that I've done in scheme, after many years
of C (and assembler), I've come to the conclusion that even
*starting*
a program in C is an exercise in premature optimization.
(Andrew Reilly comp.lang.scheme)
 

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
473,776
Messages
2,569,603
Members
45,189
Latest member
CryptoTaxSoftware

Latest Threads

Top