Making C better (by borrowing from C++)

K

Keith Thompson

E. Robert Tisdale said:
You can make C better by simply using these C++ features
and compiling with a C++ compiler.
This means that you should take care to ensure that
every C program that you write is also a valid C++ program.

Wrong. That's not making C better, that's just programming in C++.
There are several newsgroups dedicated to that topic. This is not one
of them.
 
D

Dave Vandervies

(Why did you email this to me as well as posting it?)

Dave said:
Which means if you want to replace malloc and free with new and delete,
and still want to be able to resize something, you'd also need to add
something not entirely unlike classes to hide the resizing behind,
and something not entirely unlike templates to let the something-not-
entirely-unlike-classes work for any type you care to use them for, and...

Not at all.

I have been able to program a resizable strings package using just
operator overloading in lcc-win32.

This strings are length prefixed structures, that will resize themselves
when new data is appended to them using Strcat, for instance.

They are accessed with the overloaded [ ] operators.

In the version of operator overloading in lcc-win32 you can overload
the [ ] = operator, i.e. you can know when a string is accessed
in read mode or in write mode (assignment to a string element)

int operator [ ]=(String str,int index,int newadata);

What is a String?

It obviously needs to encapsulate the length prefix and the actual
string data.
It also needs to be recognizeable to the language as something that you
can overload operators on.
To do anything useful with it in C, as opposed to your not-quite-C,
you'd also need an easy way to convert between a string and your String.

That's starting to look, feel, and smell suspiciously like a class,
even if that's not what you call it.

A similar package could be developed (and it has been started) for
a general vector facility.

And how, exactly, do you propose to do that for every possible type,
including user-defined types, without something that looks, feels, and
smells suspiciously like a template, even if that's not what you call it?


If you want C++, you know where to find it.


dave
 
I

infobahn

E. Robert Tisdale said:

Naturally. Whilst I don't claim to be perfect, I am quite accustomed
to being correct. You should try it.

Every C program should also be a valid C++ program.

By the same reasoning, every C++ program should be a valid Python
program. Is there no beginning to your reasoning ability?
I want both.

Fine. C is here. C++ is over there.
Name ten.

A silly challenge, and I'd be silly to respond. Okay, so I'm silly.
Here are ten reasons that C continues to be important:

1) C's "absence of restrictions and its generality make it more
convenient and effective for many tasks than supposedly more
powerful languages".
2) "C is not tied to any particular hardware or system [...] and
it is easy to write programs that will run without change on
any machine that supports C".
3) "C has proven to be a pleasant, expressive, and versatile
language for a wide variety of programs."
4) "It is easy to learn".
5) It "wears well as one's experience with it grows."
6) "Since C is relatively small, it can be described in a small
space, and learned quickly. A programmer can reasonably expect
to know and indeed regularly use the entire language."
7) "C has proven to be an extremely effective and expressive
language for a wide variety of programming applications."
8) Many programming languages offer support for libraries with
C bindings, so it is possible to provide functionality for
users of all these languages in one fell swoop.
9) On some platforms, C is the *only* available HLL!
10) People think in different ways. Some people think in a way
that matches C++ very well. They will be happiest and most
productive when using C++. Some people think in a way that
matches Perl very well. They will be happiest and most
productive when using Perl. And some people think in a way
that matches C very well. They will be happiest and most
productive when programming in C.

The first seven reasons are in the canonical literature, so you
ought already to have been aware of them. The last reason is
sufficient on its own to justify the existence of *any*
programming language.
C++ programmers want C++ to evolve and grow.

Why did you evade the question?

Why are you waiting then?

I'm not. I'm getting on with programming in C. When C99 becomes as
portable as C90, I'll switch over. In the meantime, I have better
things to do with my time than wait for something that's probably
never going to happen.

Yes.

Which of your target platforms

*cough* You /really/ don't understand the concept of portability, do
you?
doesn't have C99 support
for the features that Masood mentioned?

Well, he mentioned new, delete, and references, which are not
supported by C99 at all. As for the other things, they're not
sufficient on their own. As far as I'm aware, all the compilers
I have on the machine I'm currently using to compose this reply
support single-line comments. But if I put a single-line comment
in my code, it is no longer portable to implementations that
strictly enforce C90. So, until C99 in its entirety is widely
available, I shan't be using it.
and compiler developers haven't fully implemented them [yet]
so I don't think that there will be much interest
in adding the C++ features that you have mentioned.

Whoa, something we agree on.

Nonsense!

You mean you disagree with yourself? Somehow, that doesn't surprise me.
When have you every complained to a compiler developer
about missing C99 features?

No use complaining to one compiler developer. One C99 implementation
isn't anywhere near enough to persuade C90 developers to switch.
 
J

jacob navia

Dave said:
What is a String?

It obviously needs to encapsulate the length prefix and the actual
string data.
It also needs to be recognizeable to the language as something that you
can overload operators on.
To do anything useful with it in C, as opposed to your not-quite-C,
you'd also need an easy way to convert between a string and your String.

That's starting to look, feel, and smell suspiciously like a class,
even if that's not what you call it.

typedef struct _String {
size_t count;
char *content;
size_t capacity;
} String;

You can use the cast operator to convert a String to a zero
terminated string.

The difference between this and a class is that there is no
inheritance hierarchy.

You can use operator overloading with any user defined
type.
 
K

Keith Thompson

jacob navia said:
typedef struct _String {
size_t count;
char *content;
size_t capacity;
} String;

You can use the cast operator to convert a String to a zero
terminated string.

Do you mean that the cast operator is overloaded to convert from a
String to a char*? Does it just return the value of the "content"
member, or does it do some additional memory management?
 
J

jacob navia

Keith said:
Do you mean that the cast operator is overloaded to convert from a
String to a char*? Does it just return the value of the "content"
member, or does it do some additional memory management?
No, it returns the zero terminated content.

This was a difficult design decision. Since the source is distributed
with the standard distribution of lcc-win32, this decision can be
modified by the user.

The rationale is that it would be difficult to free the allocated
space, and that intuitively, a cast allocating space is not
evident.

The user can modify this string, even if this is not recommended.

The string library provides Strcat, Strcmp, Strstr, etc. Changing
code to use this strings is quite easy.
 
D

Dave Vandervies

typedef struct _String {
size_t count;
char *content;
size_t capacity;
} String;

You can use the cast operator to convert a String to a zero
terminated string.

The difference between this and a class is that there is no
inheritance hierarchy.

You can use operator overloading with any user defined
type.

....and if you put function pointers in the struct, you can build an
inheritance hierarchy into it as well. Which moves it from "looks, feels,
and smells suspiciously like a class" up to "a class by any other name".


If you want C++, you know where to find it.


dave
 
J

jacob navia

Dave said:
...and if you put function pointers in the struct, you can build an
inheritance hierarchy into it as well. Which moves it from "looks, feels,
and smells suspiciously like a class" up to "a class by any other name".


If you want C++, you know where to find it.

1: You failed to answer to:
"The difference between this and a class is that there isn't
inheritance".
There isn't any constructors/destructors either.
2: You can do object oriented programming in C without any
operator overloading. You can build classes, etc. This has
been reported several times in this group. And so what?
Then C is C++ just because you program OO with it?
 
L

Lawrence Kirby

The C99 standard explicitly allows extensions, and those extensions have
been designed keeping compatible with the C99 standard.

The standard allows extensions in some areas, yes. However it does not
allow extensions to the language syntax. If the syntax of the code does
not meet that specified in the standard then a diagnostic is required.
There are NO NEW keywords. You can still say:

int operator = 45;

int operator(int g);

etc.

Each implementation of the C standard can extend the language
in the form prescribed by the standard, and *most* of them
do.

But the extensions you described are in violation of the standard. That
isn't necessarily a problem, you just have to accept that when you use
those extensions you are programming in a different language.
Your answer is typical for people that say that C should stay
at the level of assembly language and only C++ should have any
higher level constructs.

Many of the "features" of C++ complement the OO paradigm. If you don't
have that then they are less useful. That is not the same as not useful,
but it becomes lss clear whether the benefits outweigh the costs. For
example function overloading doesn't need OO to be useful. But to
implement it would require some mechanism like name mangling for
resolving external linking, which is likely to make it link
incompatible with existing compiled C code, just like native C++ linkage
is in practice.
Operator overloading is a standard extension that is used in Fortran,
for instance, and in many other languages.

C has operator overloading. User defined operator overloading is another
matter. And if it is so wonderful, why didn't Java adopt it? :)

Lawrence
 
J

jacob navia

Lawrence said:
Randy Howard wrote:

The standard allows extensions in some areas, yes. However it does not
allow extensions to the language syntax. If the syntax of the code does
not meet that specified in the standard then a diagnostic is required.




But the extensions you described are in violation of the standard. That
isn't necessarily a problem, you just have to accept that when you use
those extensions you are programming in a different language.

Any extensions change the syntax of the language:

int __declspec(dllexport) fn(int a);

__declspec(dllexport) can be either a function call or a macro
according to the syntax. It is neither. It is a Microsoft extension
to signal that this function should be in the exported functions
list of a dll.

Is it C?

Yes.

*Any* extension will change the syntax, that is obvious.
Many of the "features" of C++ complement the OO paradigm. If you don't
have that then they are less useful. That is not the same as not useful,
but it becomes lss clear whether the benefits outweigh the costs. For
example function overloading doesn't need OO to be useful. But to
implement it would require some mechanism like name mangling for
resolving external linking, which is likely to make it link
incompatible with existing compiled C code, just like native C++ linkage
is in practice.

The C standard prescribes function overloading:

The function "sqrt" will be actually:

csqrt for complex argument
sqrtl for long double argument
sqrt for double argument
sqrtf for float argument

This functions (called type-generic) are in fact overloaded functions.

I decided to make this feature available to all users instead of
being available only to language implementors.
C has operator overloading. User defined operator overloading is another
matter. And if it is so wonderful, why didn't Java adopt it? :)

Java did not implement it, and there are several dozens packages that
try to fill this hole in the language:

Jfront: http://www.gginc.biz/jfront/index.html
Groovy: http://groovy.codehaus.org/index.html
Jpp: http://www.digiserve.com/nshaylor/jpp.html
JUMP: http://www.infa.abo.fi/~mbacklun/jump.htm
etc...

Now even Sun Microsystems is considering adding this feature to Java!
 
D

Dave Vandervies

1: You failed to answer to:
"The difference between this and a class is that there isn't
inheritance".

....which is completely irrelevant if you have function pointers, because
that makes inheritance easy to fake.
There isn't any constructors/destructors either.

In your String example that started this subthread:
:typedef struct _String {
: size_t count;
: char *content;
: size_t capacity;
:} String;
What happens when a String goes away? What happens when you assign
String to another? Initialize a String with another String?

I somehow think that what you're doing ends up looking a whole lot like
having constructors and destructors. Just because you have to explicitly
invoke them doesn't mean you don't have them, it just means you have an
even worse reinvention of them than you would otherwise.

2: You can do object oriented programming in C without any
operator overloading. You can build classes, etc. This has
been reported several times in this group. And so what?
Then C is C++ just because you program OO with it?

And there are two good reasons to do this:
-You don't have access to a C++ compiler, and even without tools that make
it easy an OO-based approach is still the best way to solve the problem
-You needorwant to have control over things the C++ compiler is doing
automatically for you but that doing it in C will expose

Neither of these will benefit from using a not-quite-C that poorly
reimplements some features that C++ has, and if using C++ is an option
there's also no reason to use a not-quite-C that poorly reimplements
some features C++ has.

If you want C++, you know where to find it.


dave

--
Dave Vandervies (e-mail address removed)
April fools postings certainly have deteriorated since the days
of Kremvax and Moscvax.
As have the fools. --Michael Rubenstein and Joe Maun in comp.lang.c
 
M

Mark McIntyre

Any extensions change the syntax of the language:

hm? void clrscr() changes the syntax?

(of MS extensions)
Is it C?

Yes.

Nope. Its a C-like dialect. Even MS's compiler will reject it when ANSI
mode is enabled.
*Any* extension will change the syntax, that is obvious.

nope.
I decided to make this feature available to all users instead of
being available only to language implementors.

Thats fine, but if you did it by overloading sqrt, its not C any more.
 
J

jacob navia

Dave said:
In your String example that started this subthread:
:typedef struct _String {
: size_t count;
: char *content;
: size_t capacity;
:} String;
What happens when a String goes away?

The same thing as when an int goes away or when a
long double complex goes away: nothing.

lcc-win32 provides a GC. This makes (if you use it)
the handling of "destructors" very easy: there is
nothing to do.

I have argued several times in this group for a GC. It changes
many ways you program, and it easies development a lot.
What happens when you assign
String to another?

Assignment of structures is well defined in C.
Initialize a String with another String?

Depends how you do it. Normally is just a copy of the
structure pointers and not of the contents.
I somehow think that what you're doing ends up looking a whole lot like
having constructors and destructors.

Surely not. But a "constructor" is a well known concept in C:


MyStruct *NewStruct(int fielda, double fieldb)
{
// xmalloc checks for NULL
MyStruct *result = xmalloc(sizeof(MyStruct));
result->fielda = fielda;
result->fieldb = fieldb;
return MyStruct;
}

Then I write:

void fn(void)
{
MyStruct *ms = NewStruct(23,67.98);
...
}


Just because you have to explicitly
invoke them doesn't mean you don't have them, it just means you have an
even worse reinvention of them than you would otherwise.


Why is it worse?

It is another conception of programming. C is not C++ and
all that bloat is not necessary. One of the most often asked
questions in the C++ newsgroups is:
"I am doing a = b and it takes forever. What is happening?"

Well, you are calling a copy constructor for each member of the array,
then you are calling the overloaded assignment operator, etc etc...

In C there isn't anything going behind your back unless explicitely
written. Operator overloading is a very simple extension, that C++
features also.
And there are two good reasons to do this:
-You don't have access to a C++ compiler, and even without tools that make
it easy an OO-based approach is still the best way to solve the problem
-You needorwant to have control over things the C++ compiler is doing
automatically for you but that doing it in C will expose

Neither of these will benefit from using a not-quite-C that poorly
reimplements some features that C++ has, and if using C++ is an option
there's also no reason to use a not-quite-C that poorly reimplements
some features C++ has.

I just question your "poorly"

You have never examined it, you are just showing your prejudices.

It is another philosophy, that's all.
If you want C++, you know where to find it.

I do not want C++. I just want to incoporate some features
that are reasonable into C, but keeping the simplicity of C,
without making a bloated language that nobody understands, not even
the compiler writers.

The specs for overloaded operator calls goes for several pages in the
C++ standard. There is no human mind that can do that, it can only
be done by a machine. The usual solution to know what are you
calling is to invoke the debugger.
 
J

jacob navia

Mark said:
hm? void clrscr() changes the syntax?

Please understand the differeence between a library call
(not an extension at all) and a real extension of the
language.

(of MS extensions)



Nope. Its a C-like dialect. Even MS's compiler will reject it when ANSI
mode is enabled.

The same with lcc-win32. __declspec(dllexport) will be rejected in ANSI
mode and you can't do dlls.

You can't do windows, you can't call any library function of the OS
you can't do anything else but use the console with putc and getc

There is no mouse, no graphics, no sound, no nothing. Most of the
software written in C uses those, so most of the software in C is
written in a "dialect" then. Who cares?

Extensions are a modification of the syntax, however slight.

"__builtin" constructs, "__special__" etc etc. Gcc uses them,
MSVC uses them, etc. This are necessary adaptations of the
syntax to particular environments. Without them, you couldn't
do any real world programming.
Thats fine, but if you did it by overloading sqrt, its not C any more.

If I would have done it by hardwiring the overloaded functions into
the compiler it would be the same thing. This functions are overloaded
BY DEFINITION in the standard itself.

Whether this feature is available to users too doesn't matter. They
*are* overloaded functions, i.e. functions that call a set of procedures
dispatching by the type of the arguments!
 
C

Chris Croughton

The same with lcc-win32. __declspec(dllexport) will be rejected in ANSI
mode and you can't do dlls.

You can't do windows, you can't call any library function of the OS
you can't do anything else but use the console with putc and getc

In that case it's not C compliant as a hosted implementation, because a
hosted implementation has to provide the file access functions (among
others). But why can't you call library functions of the OS? Oh,
perhaps you can't on some minority OS because it has some weird
parameter passing method which requires an extension (but it should be
possible to compile so that the method is what the compiler produces by
default), but the OS (or compiler implementer) can always provide their
own interface functions.
There is no mouse, no graphics, no sound, no nothing. Most of the
software written in C uses those, so most of the software in C is
written in a "dialect" then. Who cares?

'Most'? I might agree with "most of the software purchased" (since that
includes all of the MS stuff), but I doubt that its most of the software
written. I have never written professionally[1] a C program which used
a mouse, graphics or sound, and I've written a lot of C code.

[1] As in one which I was employed to write, as opposed to writing for
my own amusement.
Extensions are a modification of the syntax, however slight.

"__builtin" constructs, "__special__" etc etc. Gcc uses them,
MSVC uses them, etc. This are necessary adaptations of the
syntax to particular environments. Without them, you couldn't
do any real world programming.

If they are done according to the standards, they don't modify the
syntax because they are explicitly in the implementer's namespaces, and
a conforming program can not use them explicitly (if an implementation
uses them in macros, that's nothing to do with the program). They
generally look like macros (__attribute__(packed) for instance) and so
do not alter the syntax.
If I would have done it by hardwiring the overloaded functions into
the compiler it would be the same thing. This functions are overloaded
BY DEFINITION in the standard itself.

Which is, admittedly, a big mistake in the standard, I was appalled when
I found the tgmath.h header in the C99 spec. Overloading should either
be generally defined so that it is available to user programs as well
(or other extensions such as typeof) or it should have been left out.
Whether this feature is available to users too doesn't matter. They
*are* overloaded functions, i.e. functions that call a set of procedures
dispatching by the type of the arguments!

They are indeed. A horrible botch.

Chris C
 
L

Lawrence Kirby

Nope. In addition to adding new library functions, there can be extra
predefined macros, #pragmas and w hhole host of areas where the
implementation defines behaviour that the standard leaves undefined or
unspecified. For example an implementation may specify a well-defined
result for general integer to pointer conversions, i=i++, void main() etc.
These are extensions to the language that use the existing syntax.
Please understand the differeence between a library call (not an
extension at all) and a real extension of the language.

Please understand that the standard library is part of the C language.
The same with lcc-win32. __declspec(dllexport) will be rejected in ANSI
mode and you can't do dlls.

You can't do windows, you can't call any library function of the OS
you can't do anything else but use the console with putc and getc

There is no mouse, no graphics, no sound, no nothing. Most of the
software written in C uses those, so most of the software in C is
written in a "dialect" then. Who cares?

Anyboy can care when they don't need these things.
Extensions are a modification of the syntax, however slight.

The language syntax is what is defined by the language grammar, it is not
defined by the set of strictly conforming programs.
"__builtin" constructs, "__special__" etc etc. Gcc uses them, MSVC uses
them, etc. This are necessary adaptations of the syntax to particular
environments. Without them, you couldn't do any real world programming.

There are plenty of things you can't do without using extensions, but
there are plenty of things you can do. For example many of the standard
Unix tools could be written in standard C.
If I would have done it by hardwiring the overloaded functions into the
compiler it would be the same thing. This functions are overloaded BY
DEFINITION in the standard itself.

I don't follow.
Whether this feature is available to users too doesn't matter. They
*are* overloaded functions, i.e. functions that call a set of procedures
dispatching by the type of the arguments!

?

Lawrence
 
J

jacob navia

Chris said:
In that case it's not C compliant as a hosted implementation, because a
hosted implementation has to provide the file access functions (among
others).

fopen et al are available of course...
But why can't you call library functions of the OS?

Because they are _stdcall and that is an extension my dear.
Oh,
perhaps you can't on some minority OS because it has some weird
parameter passing method which requires an extension

Exactly. You get it now. There are several other problems too.

(but it should be
possible to compile so that the method is what the compiler produces by
default),

No, it is not possible since for variable argument functions like
printf that convention CAN't be used! I have to keep BOTH you see?


but the OS (or compiler implementer) can always provide their
own interface functions.

Of course, I would have to rewrite the 15 000 APIs that Windows
offers and that my compiler allows access to.

Only that. Very easy.

And keep 2-5 people maintainig them to keep track of changes to the API

All of this to avoid writing

_stdcall

In the headers.
There is no mouse, no graphics, no sound, no nothing. Most of the
software written in C uses those, so most of the software in C is
written in a "dialect" then. Who cares?


'Most'? I might agree with "most of the software purchased" (since that
includes all of the MS stuff), but I doubt that its most of the software
written. I have never written professionally[1] a C program which used
a mouse, graphics or sound, and I've written a lot of C code.

OK. Then you can use "pure C" as you wish. lcc-win32 is a C compiler
that targets the Windows desktop platform. Not your stuff.
If they are done according to the standards, they don't modify the
syntax because they are explicitly in the implementer's namespaces, and
a conforming program can not use them explicitly (if an implementation
uses them in macros, that's nothing to do with the program). They
generally look like macros (__attribute__(packed) for instance) and so
do not alter the syntax.

As I explained already, all the extensions of lcc-win32 are exactly like
that: they do not use the user's namespace and a conforming program
cannot use them explicitely unless they use the extension.

For instance a normal C program can't write:

int operator+(myStruct a,myStruct b);

So if they do write this they are using lcc-win32's extensions.
Which is, admittedly, a big mistake in the standard, I was appalled when
I found the tgmath.h header in the C99 spec.

Of course. The standard is mistaken. When you like it, you are "FOR
STANDARD C"!! when you do not like it you say the standard is mistaken.

Overloading should either
be generally defined so that it is available to user programs as well
(or other extensions such as typeof) or it should have been left out.

That is EXACTLY WHAT I AM DOING. I am letting all users do the
overloading if they wish!
They are indeed. A horrible botch.

Chris C


No, a normal need: It is very difficult and error prone to memorize
several similar function names, and not make a mistake when calling
the one or the other. This is a work that machines do very well. They
can do dumb things very quickly and do not get bored. So why do not
let the machines do the work for you?
 
J

jacob navia

Lawrence said:
Anyboy can care when they don't need these things.

OK FINE.

Your programs do not use anything but files, and you get user input
with getc()

lcc-win32 is a compiler that targets the desktop environment.

You can do all the things I mentioned above, and thousands I did
not mention, like network programming, distributed applications
programming what have you.

Let the users decide which is more practical then.

I am sure an ANSIC only version of a C compiler would be smashing
success !

jacob
 
S

Stephen Sprunk

jacob navia said:
lcc-win32 is a compiler that targets the desktop environment.

comp.lang.c is a newsgroup that targets ISO C.
You can do all the things I mentioned above, and thousands I did
not mention, like network programming, distributed applications
programming what have you.

Let the users decide which is more practical then.

There are plenty of other newsgroups where users can go for
implementation-specific information. This is not one of them.

S
 
I

infobahn

jacob said:
I am sure an ANSIC only version of a C compiler would be smashing
success !

So am I. I'd break a several-year tradition of mine and actually
spend money on such software, provided it had the following features:

1) Full support for C90 language and library
2) Full support for C99 language and library
3) No diagnostics except those required by the Standard for
syntax errors and constraint violations
4) Available for at least Win32 and Linux
5) No extensions whatsoever

That would be an extremely useful implementation indeed.
 

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,755
Messages
2,569,536
Members
45,009
Latest member
GidgetGamb

Latest Threads

Top