C as a Subset of C++ (or C++ as a superset of C)

T

Tim Rentsch

James Kuyper said:
On 08/28/2012 09:32 AM, David Brown wrote:
...

If you put two types in a union, within the scope of that union
declaration a conforming implementation must take aliasing between those
two types into consideration any time it's dealing with pointers that
could be pointing at different members of the same union object.

Obviously this isn't right, since if it were there
would be no reason for the "one special guarantee"
for structure access.
 
T

Tim Rentsch

Keith Thompson said:
Kenneth Brody said:
so "void*" says pointer to void. This is not "nothing" or "unknown",
in that sense void is not much different from "struct nix" when you
never actually define "struct nix" somewhere. It behaves a bit
different in terms of implicit conversions, sure, but the sematic is
the same.

Not really. A `char*` pointer points to an object of type `char`. A
`void*` pointer does not point to an object of type `void`, because
there is no such thing.

Any type of pointer to object or incomplete type (i.e., any pointer
other than a function pointer) points to some object in memory (or to
nothing if it's currently a null pointer). What's special about `void*`
is that, while you can perform certain pointer operations on it, you
can't access the object it points to without first converting it to some
other pointer type.
[...]

While technically correct that "void *" doesn't point to an object of
type "void" because there's no such thing, I think it is convenient to
think of it in those terms.

I disagree. That is, I agree that it's technically correct (the
best kind of correct!), but I think it's correct in every other
sense as well. [snip elaboration]

I would say exactly the opposite - a pointer of type 'void *'
points at something of type void. In fact all valid addresses
(arguably even those pointing past the end of arrays) refer
to legimate void objects. Just because you can't /do/ anything
with those void objects, as such, doesn't make them any less
legimate.

To give a more concrete argument, the rules for derived types,
in particular pointer types, says "A pointer type describes an
object whose value provides a reference to an entity of the
referenced type." There is no special mention or exception
made for pointers to void.
 
T

Tim Rentsch

David Brown said:
On 08/28/2012 09:32 AM, David Brown wrote:
...

If you put two types in a union, within the scope of that union
declaration a conforming implementation must take aliasing between those
two types into consideration any time it's dealing with pointers that
could be pointing at different members of the same union object.

Correct me if I'm wrong, but I believe this is actually just an
"unwritten rule" that all compilers have agreed to follow. [snip]

Actually it (ie, the semantics of union member access) is a written
rule, it's just not written in a way that makes it obvious.
 
T

Tim Rentsch

Jens Gustedt said:
Am 29.08.2012 10:44, schrieb David Brown:
On 29/08/2012 10:19, Jens Gustedt wrote:
The great thing about standards is that there are so many to choose from!
:)

I don't know that type-punning was the "main intent" of unions - I think
saving storage space was the main motivation.

I was perhaps pushing a bit too far, but type punning has been around
since the beginning. And if I understand it right it was the idea of
the committee to affirm that it always had been an intented use case,
and that just the wording in the standard had been too ambiguous.
[snip unrelated]

The phrasing in C90 made the type punning semantics obvious.
The original wording in C99 had the same semantics as was
intended for C90, but this was not obvious. The DR that
introduced the clarifying footnote makes it clear that
there was no change in intention, only a change in wording.
 
T

Tim Rentsch

Keith Thompson said:
Jens Gustedt said:
No, this is not an "unwritten rule" for C. C99 originally had a
wording that could be interpreted as you state. A corrigendum has made
it clear that it is not intended. Type-punning in C works as long as
the value that you are reading is valid for the type through which you
are doing so.

A footnote in the C standard clarifies that:

95) If the member used to read the contents of a union object is not
the same as the member last used to store a value in the object, the
appropriate part of the object representation of the value is
reinterpreted as an object representation in the new type as described
in 6.2.6 (a process sometimes called ''type punning''). This might be
a trap representation.

Yes. That footnote was added by Technical Corrigendum 3. It appears
in N1256 (though oddly without a change bar), [snip]

If you look near the top of the page the footnote is on,
you should find the change bar next to paragraph 3,
to show that the footnote was added.
 
K

Keith Thompson

Tim Rentsch said:
Keith Thompson said:
While technically correct that "void *" doesn't point to an object of
type "void" because there's no such thing, I think it is convenient to
think of it in those terms.

I disagree. That is, I agree that it's technically correct (the
best kind of correct!), but I think it's correct in every other
sense as well. [snip elaboration]

I would say exactly the opposite - a pointer of type 'void *'
points at something of type void. In fact all valid addresses
(arguably even those pointing past the end of arrays) refer
to legimate void objects. Just because you can't /do/ anything
with those void objects, as such, doesn't make them any less
legimate.

So you believe that there's such a thing as a "void object"?

An "object" is by definition a "region of data storage in the
execution environment, the contents of which can represent values".
For a void object, what is the size of this region, and what values
can its contents represent?
To give a more concrete argument, the rules for derived types,
in particular pointer types, says "A pointer type describes an
object whose value provides a reference to an entity of the
referenced type." There is no special mention or exception
made for pointers to void.

Or for pointers to other incomplete types, or for null pointers.
I suggest that this is an oversight. I'll also note that it uses
the word "entity", not "object". Neither void pointers nor function
pointers refer to objects.
 
K

Keith Thompson

Tim Rentsch said:
Keith Thompson said:
Jens Gustedt said:
No, this is not an "unwritten rule" for C. C99 originally had a
wording that could be interpreted as you state. A corrigendum has made
it clear that it is not intended. Type-punning in C works as long as
the value that you are reading is valid for the type through which you
are doing so.

A footnote in the C standard clarifies that:

95) If the member used to read the contents of a union object is not
the same as the member last used to store a value in the object, the
appropriate part of the object representation of the value is
reinterpreted as an object representation in the new type as described
in 6.2.6 (a process sometimes called ''type punning''). This might be
a trap representation.

Yes. That footnote was added by Technical Corrigendum 3. It appears
in N1256 (though oddly without a change bar), [snip]

If you look near the top of the page the footnote is on,
you should find the change bar next to paragraph 3,
to show that the footnote was added.

You're right (though it would have made sense to have a change bar on
the footnote itself as well).

For those following along, this is footnote 82, section 6.5.2.3p3 in
N1256, foonote 95, same section in N1570.
 
T

Tim Rentsch

Keith Thompson said:
Tim Rentsch said:
Keith Thompson said:
While technically correct that "void *" doesn't point to an object of
type "void" because there's no such thing, I think it is convenient to
think of it in those terms.

I disagree. That is, I agree that it's technically correct (the
best kind of correct!), but I think it's correct in every other
sense as well. [snip elaboration]

I would say exactly the opposite - a pointer of type 'void *'
points at something of type void. In fact all valid addresses
(arguably even those pointing past the end of arrays) refer
to legimate void objects. Just because you can't /do/ anything
with those void objects, as such, doesn't make them any less
legimate.

So you believe that there's such a thing as a "void object"?

Sure. void is an object type -- an incomplete object type, but
still an object type. What's wrong with having there be void
objects?
An "object" is by definition a "region of data storage in the
execution environment, the contents of which can represent values".
For a void object, what is the size of this region, and what values
can its contents represent?

Same answers as for 'struct foo' when that is an incoomplete
type, namely, we don't know and we don't know. One thing
we _do_ know that is very useful is where the object starts.
Or for pointers to other incomplete types, or for null pointers.

Pointers to incomplete object types still refer to objects.

The null pointer case is a red herring, just like a pointer
to one-past-an-array - the pointer still provides a reference
to something of the referenced type, even if in some cases
we can't actually get a "thing" by dereferencing. We can't
get a "thing" by dereferencing a pointer to an incomplete
object type either, but there still can be an object there
of that type even if we don't know what it is.
I suggest that this is an oversight. I'll also note that it uses
the word "entity", not "object". Neither void pointers nor function
pointers refer to objects.

The word "entity" is used only because functions and objects
are different. A pointer-to-function refers to a function;
a pointer to an object type refers to an object, whether
it is of complete object type or incomplete object type.

The world is just a lot simpler if we assume that there are void
objects along with all the other kinds of objects. I'm sure a
consistent model can be constructed where a pointer-to-void
points to "nothing", but why would we do that when it will just
complicate things? For example, converting a pointer to a
pointer-to-character type gives a pointer to the first byte of
the object. If a (void*) pointer points to "nothing", converting
it to a (char*) will end up being undefined behavior. Those
kinds of problems seem like a big headache for no tangible value.
 
L

lawrence.jones

Keith Thompson said:
Tim Rentsch said:
Keith Thompson said:
Yes. That footnote was added by Technical Corrigendum 3. It appears
in N1256 (though oddly without a change bar), [snip]

If you look near the top of the page the footnote is on,
you should find the change bar next to paragraph 3,
to show that the footnote was added.

You're right (though it would have made sense to have a change bar on
the footnote itself as well).

Indeed. The automated diff mark process falls down in this case due to
the way footnotes are handled in troff and mm. The editor usualy makes
an effort to correct such misses manually, but managed to overlook that
one.
 
L

lawrence.jones

Malcolm McLean said:
Yes, we badly need one programming language that does everything.

What you'll get is a programming language that does everything badly.
 
M

Malcolm McLean

בת×ריך ×™×•× ×©×œ×™×©×™, 11 בספטמבר 2012 16:14:25 UTC+1, מ×ת (e-mail address removed):
What you'll get is a programming language that does everything badly.
That's arguably OK. Better to do every badly, but at least work, everywhere, than have a finely honed, expensively developed, very interesting program, in Lisp.
 
N

Nick Keighley

That's arguably OK. Better to do every badly, but at least work, everywhere, than have a finely honed, expensively developed, very interesting program, in Lisp.

oh. I assumed you were proposing Lisp *as* the universal hammer. Which
blub are you proposing then? PL/I was the last attempt.
 
M

Malcolm McLean

בת×ריך ×™×•× ×¨×‘×™×¢×™, 12 בספטמבר 2012 09:01:53 UTC+1, מ×ת Nick Keighley:
On Sep 11, 11:14 pm, Malcolm McLean <[email protected]>

oh. I assumed you were proposing Lisp *as* the universal hammer. Which
blub are you proposing then? PL/I was the last attempt.
I'd say it needs essentially C syntax - loops, curly brackets, non-flow control non-arithemtical functionality implemented as functions rather than the core language. That's generally been accepted.

But C itself isn't a good universal language, because of the buffer overflow and wild pointer issue. Also because of the difficulties in representing higher-level contructs, like classes, graphs, and metacode. Even structs have no way of serialising without writing special functions for each case.

Also the proliferation of integer types is unacceptable.
 
N

Nick Keighley

בת×ריך ×™×•× ×¨×‘×™×¢×™, 12 בספטמבר 2012 09:01:53 UTC+1, מ×ת Nick Keighley:> On Sep 11, 11:14 pm, Malcolm McLean <[email protected]>

Malcolm Mclean said
apparently for small values of "everything"

I'd say it needs essentially C syntax - loops, curly brackets, non-flow control non-arithemtical functionality implemented as functions rather than the core language. That's generally been accepted.

by whom? You seem to saying we need a single low level procedural
language. I'm not sure your wish-list is consistent. lets call it
Single Procedural Language (SPL)
But C itself isn't a good universal language, because of the buffer overflow and wild pointer issue.

use Java? But that interposes a VM. How do you avoid buffer overflow
without runtime overhead? Could we write a device driver in SPL? What
about cryto, compression or embedded code?
Also because of the difficulties in representing higher-level contructs, like classes, graphs, and metacode.

templates? Can even Java do all these things?
Even structs have no way of serialising without writing special functionsfor each case.

Java? Python? Sounds potentially expensive
Also the proliferation of integer types is unacceptable.

but also useful. is there a current langauage thate meets your
criteria?
 
N

Nick Keighley

I believe that "we badly need" implies that he knows of no such language.

ok. is there one that matches most of the requirement? I'm dubious
that a language can have address safety, generics, metacode and
builtit serialization whilst still preserving the low level access
that is one of C's powers.
 
M

Malcolm McLean

בת×ריך ×™×•× ×¨×‘×™×¢×™, 12 בספטמבר 2012 14:31:18 UTC+1, מ×ת Nick Keighley:
by whom? You seem to saying we need a single low level procedural
language. I'm not sure your wish-list is consistent. lets call it
Single Procedural Language (SPL)
Most modern new languages go for curly braces and a superfically at least
C-like syntax. But there are exceptions, of course. If there were no exceptions
at all then saying "we need essential C-like syntax" would be as fatuous as
saying "we should standardise on Arabic numerals".
 
B

BartC

Malcolm McLean said:
בת×ריך ×™×•× ×¨×‘×™×¢×™, 12 בספטמבר 2012 09:01:53 UTC+1, מ×ת Nick Keighley:
I'd say it needs essentially C syntax - loops, curly brackets, non-flow
control non-arithemtical functionality implemented as functions rather
than the core language. That's generally been accepted.

Not by everyone. Or it's been forced on them. A number of syntax styles are
possible for a given language, of which C-style is one, characterised by too
much punctuation and lots of curly braces.
Also the proliferation of integer types is unacceptable.

Proliferation? Typically there are 8 combinations of signed/unsigned, and
width (8,16,32,64 bits). For discrete int variables, you might only use one
or two. For packed arrays and structs, you need to have the choice.
But C itself isn't a good universal language, because of the buffer
overflow and wild pointer issue. Also because of the difficulties in
representing higher-level contructs, like classes, graphs, and metacode.
Even structs have no way of serialising without writing special functions
for each case.

No, C is hopeless. There are plenty of improvements that can be made(**),
but you will just end up with some ghastlier version of C++. I don't believe
a single universal language can be created that will please everyone.

(** I recently finished designing a low-level implementation language that
pretty much does what C does. When I listed the differences (mostly
improvements in my view!) from C, I stopped when I got to 100. And that
didn't include syntax which is utterly different. But then, it's not hard to
tidy up a language that's 40 years old.)
 
M

Malcolm McLean

בת×ריך ×™×•× ×¨×‘×™×¢×™, 12 בספטמבר 2012 16:22:06 UTC+1, מ×ת Bart:
Proliferation? Typically there are 8 combinations of signed/unsigned, and
width (8,16,32,64 bits). For discrete int variables, you might only use one
or two. For packed arrays and structs, you need to have the choice.
Consider this

int16 *readaudiosamples(void *context);
void playaudiosamples(short *wave, int N);
 

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,772
Messages
2,569,593
Members
45,111
Latest member
KetoBurn
Top