Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Diagram showing memory access

51 views
Skip to first unread message

Frederick Gotham

unread,
Jun 27, 2020, 4:17:53 PM6/27/20
to

[This post is equally relevant to C++ and C and so I'm multi-posting to comp.lang.c++ and comp.lang.c]

Fourteen years ago, the following thread was started on comp.std.c++:

https://groups.google.com/d/msg/comp.std.c++/uVbAnGYxclc/YXCwnpS1NogJ

You can see the contents of the original post below.

I'd like to ask if anyone still has the JPG image file referenced in the below post, or if there's any way at all of retrieving it?


On Monday, May 8, 2006 at 6:34:09 PM UTC+1, Tomás wrote:
> I'm sure a lot of you have seen the following code which demonstrates why
> we can't implicitly convert from:-
>
> char**
>
> to:
>
> const char**
>
>
> Here's the code (written originally by James Kanze):
>
> const char c = 'a';
> char* p;
> char** pp = &p;
> const char** ppc = pp; // Supposing that this were not illegal.
>
> *ppc = &c; // Oops: where does p point?
> *p = 'b'; // And what is wrong here?
>
>
> I've read the above code many times but never understood it. Even when I
> thought about it thoroughly and slowly, I couldn't comprehend what was
> going on.
>
> Anyway, I came across the code again today, and finally I resolved to
> grasp an understanding of it once and for all. So I drew a diagram, which,
> after a few minutes of analysing, made me understand. With the hope of
> helping others, here's the diagram:
>
> http://img315.imageshack.us/img315/2876/undconst6kk.jpg
>
> I've posted this to more than one newsgroup, so if you would like to
> reply, I'd appreciate if you would keep the discussion in comp.lang.c++.
>
> -Tomás

Chris M. Thomasson

unread,
Jun 27, 2020, 4:43:21 PM6/27/20
to
On 6/27/2020 1:17 PM, Frederick Gotham wrote:
>
> [This post is equally relevant to C++ and C and so I'm multi-posting to comp.lang.c++ and comp.lang.c]
>
> Fourteen years ago, the following thread was started on comp.std.c++:
>
> https://groups.google.com/d/msg/comp.std.c++/uVbAnGYxclc/YXCwnpS1NogJ
>
> You can see the contents of the original post below.
>
> I'd like to ask if anyone still has the JPG image file referenced in the below post, or if there's any way at all of retrieving it?

The image is most likely gone forever. Unless something just happened to
archive it. Fwiw, James Kanze is very smart, I had a nice time
conversing with him.

Chris M. Thomasson

unread,
Jun 27, 2020, 4:47:14 PM6/27/20
to
On 6/27/2020 1:43 PM, Chris M. Thomasson wrote:
> On 6/27/2020 1:17 PM, Frederick Gotham wrote:
>>
>> [This post is equally relevant to C++ and C and so I'm multi-posting
>> to comp.lang.c++ and comp.lang.c]
>>
>> Fourteen years ago, the following thread was started on comp.std.c++:
>>
>>
>> https://groups.google.com/d/msg/comp.std.c++/uVbAnGYxclc/YXCwnpS1NogJ
>>
>> You can see the contents of the original post below.
>>
>> I'd like to ask if anyone still has the JPG image file referenced in
>> the below post, or if there's any way at all of retrieving it?
>
> The image is most likely gone forever. Unless something just happened to
> archive it. Fwiw, James Kanze is very smart, I had a nice time
> conversing with him.
[...]

Perhaps look for it on the wayback machine. Fwiw, it actually crawled an
old website that I used to have:

http://web.archive.org/web/20060213220325/http://appcore.home.comcast.net/

Bart

unread,
Jun 27, 2020, 5:05:33 PM6/27/20
to
On 27/06/2020 21:46, Stefan Ram wrote:
> Frederick Gotham <cauldwel...@gmail.com> quoted:
> |const char c = 'a';
> |char* p;
> |char** pp = &p;
> |const char** ppc = pp;
>
> pp p ppc c
> .---. .---. .---. .---.
> | o--------->| |<---------o | | a |
> '---' '---' '---' '---'

This may be fine for single pointers. The chances are that these
represent arrays and strings.

I started writing down the possible combinations of char** then realised
I wasn't quite sure what they all were!

The C type system really doesn't help. Looking at just the simplest
char* type, this could point to one character (a 0D array), or the first
of a sequence (a 1D array of char or a zero-terminated string). With the
possibilities with each extra * growing.

Mike Terry

unread,
Jun 27, 2020, 5:44:10 PM6/27/20
to
On 27/06/2020 21:46, Stefan Ram wrote:
> Frederick Gotham <cauldwel...@gmail.com> quoted:
> |const char c = 'a';
> |char* p;
> |char** pp = &p;
> |const char** ppc = pp;
>
> pp p ppc c
> .---. .---. .---. .---.
> | o--------->| |<---------o | | a |
> '---' '---' '---' '---'
>
> |*ppc = &c;
>
> pp p ppc c
> .---. .---. .---. .---.
> | o--------->| | | o--------->| a |
> '---' '---' '---' '---'
>
|*ppc = &c;

pp p ppc c
.---. .---. .---. .---.
| o--------->| o |<---------o | | a |
'---' '-|-' '---' '---'
| ^
| |
'-------------------------'

|*p = 'b';

pp p ppc c
.---. .---. .---. .---.
| o--------->| o |<---------o | | b?|
'---' '-|-' '---' '---'
| ^
| |
'-------------------------'

(but c is const)

Mike.

Richard Damon

unread,
Jun 27, 2020, 6:02:58 PM6/27/20
to
On 6/27/20 4:46 PM, Stefan Ram wrote:
> Frederick Gotham <cauldwel...@gmail.com> quoted:
> |const char c = 'a';
> |char* p;
> |char** pp = &p;
> |const char** ppc = pp;
>
> pp p ppc c
> .---. .---. .---. .---.
> | o--------->| |<---------o | | a |
> '---' '---' '---' '---'
>
> |*ppc = &c;
>
> pp p ppc c
> .---. .---. .---. .---.
> | o--------->| | | o--------->| a |
> '---' '---' '---' '---'
>
> |*p = 'b';
>
shouldn't that be: (for *ppc = &c; )

pp p ppc c
.---. .---. .---. .---.
| o--------->| o |<---------o | | a |
'---' '-|-' '---' '---'
| ^
|_________________________|

and it is the
const char** ppc = pp;
that is currently not allowed, and causes the issue, as it means that
*ppc has type (const char*), and thus accepts the address of a const
char, but it also is *pp which has type char* so **pp (or *p) is seen as
a writeable char object, which it isn't.

Keith Thompson

unread,
Jun 27, 2020, 7:36:12 PM6/27/20
to
Bart <b...@freeuk.com> writes:
[...]
> The C type system really doesn't help. Looking at just the simplest
> char* type, this could point to one character (a 0D array), or the
> first of a sequence (a 1D array of char or a zero-terminated
> string). With the possibilities with each extra * growing.

A value of type char* points to a single object of type char. [*]

That object may or may not be the initial element of an array object.

Please don't try to make it sound more complicated than it really is.

[*] Or it may be a null pointer, or an invalid pointer, or a pointer
just past the end of an array object.

--
Keith Thompson (The_Other_Keith) Keith.S.T...@gmail.com
Working, but not speaking, for Philips Healthcare
void Void(void) { Void(); } /* The recursive call of the void */

Bart

unread,
Jun 27, 2020, 8:44:14 PM6/27/20
to
On 28/06/2020 00:36, Keith Thompson wrote:
> Bart <b...@freeuk.com> writes:
> [...]
>> The C type system really doesn't help. Looking at just the simplest
>> char* type, this could point to one character (a 0D array), or the
>> first of a sequence (a 1D array of char or a zero-terminated
>> string). With the possibilities with each extra * growing.
>
> A value of type char* points to a single object of type char. [*]
>
> That object may or may not be the initial element of an array object.
>
> Please don't try to make it sound more complicated than it really is.
>
> [*] Or it may be a null pointer, or an invalid pointer, or a pointer
> just past the end of an array object.
>

/Could/ a char* be used to point to the first of several or many
characters? Such as the first argument here:

fopen("hello.c","w")

If so then my point stands. I was replying to somebody who'd posted
diagrams, which need not correspond to the intended uses of those types.

Keith Thompson

unread,
Jun 27, 2020, 9:09:20 PM6/27/20
to
Bart <b...@freeuk.com> writes:
> On 28/06/2020 00:36, Keith Thompson wrote:
>> Bart <b...@freeuk.com> writes:
>> [...]
>>> The C type system really doesn't help. Looking at just the simplest
>>> char* type, this could point to one character (a 0D array), or the
>>> first of a sequence (a 1D array of char or a zero-terminated
>>> string). With the possibilities with each extra * growing.
>>
>> A value of type char* points to a single object of type char. [*]
>>
>> That object may or may not be the initial element of an array object.
>>
>> Please don't try to make it sound more complicated than it really is.
>>
>> [*] Or it may be a null pointer, or an invalid pointer, or a pointer
>> just past the end of an array object.
>
> /Could/ a char* be used to point to the first of several or many
> characters? Such as the first argument here:
>
> fopen("hello.c","w")

Of course it could. That's what I said.

> If so then my point stands.

So does mine.

> I was replying to somebody who'd posted
> diagrams, which need not correspond to the intended uses of those
> types.

David Brown

unread,
Jun 28, 2020, 4:12:03 AM6/28/20
to
If I tell you "there's a letter A written on a piece of paper", then
that letter could be stand-alone, it could be part of a word, part of a
sentence, part of a Shakespeare play or Fermat's mythical proof of his
theorem. But it is pointless to try to consider all the possibilities.

A valid char* points to an object of type char. No more, no less. Like
any object in C, that may or may not be part of an array.

You have worked long and hard through the years to make yourself as
confused as possible about C pointers, and to find new ways to hate the
language. Please don't spread that confusion to others. When someone
asks fundamental questions about C in this newsgroup, it is an
opportunity for you to shut up and listen - maybe you'll learn
something, or gain some insight. Spreading FUD is not helpful to
anyone, and just annoys people.


Bart

unread,
Jun 28, 2020, 6:05:18 AM6/28/20
to
The diagrams posted by Stefan Ram (setting aside the error) could have
been misleading as to the intentions of the code.

Yes, in any language with incremental pointers, P /could/ point to 1 or
N objects. But only in C is that used as a fundamental idiom.

So with char** pp, in C there is no problem in accessing a terminal char
object as either:

**pp // as per the diagram
pp[i][j] // rather differently to the diagram
*pp[i]; // differently yet again
(*pp)[i]; // and again

These require 4 different diagrams.

So, you want to hide all this from the OP? OK.

There further differences when the target you want to deal with is a
C-style zero-terminated string implemented char* rather than a char:

*pp; // pp points to a single char* string
pp[i]; // When pp is an array of char* in C style


Richard Damon

unread,
Jun 28, 2020, 7:47:21 AM6/28/20
to
Actually, the digrams given implied that each pointer was to a single
object and not into an array (since the target of the pointer was a
single box.

In fact, since we were also given the program that it represents, we
know that fact.

Yes, in C we use the exact same syntax for a pointer to a single object,
and a pointer into an array of objects, and it is the job of the
programmer to keep this distinction clear (if he needs to). This is all
in line with the goal of the language which was designed to be a light
weight language capable of producing very efficient code, based on a
trust that the programmer will 'follow the rules' and do things right.

Bart

unread,
Jun 28, 2020, 11:39:01 AM6/28/20
to
C also has the syntax to do it properly; suppose S is a typedef (eg. for
char*):

S* A;

This is the idiom used when A is a dynamically allocated array of A. It
could also be intended to point to a single A (maybe in the middle of a
struct). Access to elements is via A[i].

The proper way is:

S (*A)[];

A is not a pointer to array of S, not a pointer S. Access though is via
(*A)[i]. But nobody uses this (except me during C code generation, but
even I don't bother usually because of the fiddly syntax).

This doesn't fix everything though as, when bounds are present, this can
be still be indexed, without error, as A[i] as well as (*A)[i]. The
former expression is an access to the (i-1)th array, which may or may
not exist.

Alf P. Steinbach

unread,
Jun 28, 2020, 8:12:37 PM6/28/20
to
On 28.06.2020 20:16, Stefan Ram wrote:
> Richard Damon <Ric...@Damon-Family.org> writes:
>> Yes, in C we use the exact same syntax for a pointer to a single object,
>> and a pointer into an array of objects, and it is the job of the
>> programmer to keep this distinction clear (if he needs to).
>
> The importance of this distinction has perhaps been somewhat
> overemphasized in some recent posts to this newsgroup. When
> an expression has type "T*" and has a valid non-zero value at
> runtime, then it points to an object of type T. This is still
> true when this object happens to be some kind of subobject.

The way I use the term "valid" there are a very large number of valid
non-zero pointer values that don't point to objects.

The address after any array is a valid pointer value. There needs not be
any object there, or of the pointer's referent type. Additionally, for
the purpose of forming a pointer to a pseudo-object after, the C++
standard specifies that any single object can be regarded as an array.

Also, no valid function pointer points to an object.

Then, but this is only for C++, after the object that an object pointer
points to, has been destroyed, there is no object there. But until the
storage is deallocated there is storage that can be reused. And the
standard specifies how the pointer can be used for that.

As far as I know there is no commonly accepted reasonably short term for
"a pointer that points to an object", i.e. a pointer that can be
dereferenced (note: in C as I recall one can do `&*p` for a pointer to
beyond array). In my old C++03 pointers tutorial, which featured for a
time as reference in Wikipedia, I invented the awful name RealGood
pointer. Happily that term (and it's cousin URG, UnRealGood) never
caught on.

- Alf

Chris M. Thomasson

unread,
Jun 28, 2020, 8:23:24 PM6/28/20
to
On 6/28/2020 5:12 PM, Alf P. Steinbach wrote:
> On 28.06.2020 20:16, Stefan Ram wrote:
>> Richard Damon <Ric...@Damon-Family.org> writes:
>>> Yes, in C we use the exact same syntax for a pointer to a single object,
>>> and a pointer into an array of objects, and it is the job of the
>>> programmer to keep this distinction clear (if he needs to).
>>
>>    The importance of this distinction has perhaps been somewhat
>>    overemphasized in some recent posts to this newsgroup. When
>>    an expression has type "T*" and has a valid non-zero value at
>>    runtime, then it points to an object of type T. This is still
>>    true when this object happens to be some kind of subobject.
>
> The way I use the term "valid" there are a very large number of valid
> non-zero pointer values that don't point to objects.
[...]

For some reason, this reminds me a special pointer value I use in a
highly experimental atomic stack algorihtm:

https://groups.google.com/forum/#!original/comp.arch/k1Qr520dcDk/4vl_jiVRBQAJ

Here is the definition:

// hackish!
#define SPECIAL ((node*)0xDEADBEEF)


Very hackish, however, its never dereferenced, just used as a special value.

Richard Damon

unread,
Jun 29, 2020, 8:34:44 AM6/29/20
to
THe best term I can think of is a dereferenceable (an pointer, can of
course be dereferenced, but if it doesn't point to an object you have
undefined behavior).

One other point, I thought that a pointer to dynamic memory, once that
memory was free()ed, could now hold a 'trap value', which is in one
sense, no longer a 'valid' value, as merely inspecting the value of the
pointer could terminate your program.

Alf P. Steinbach

unread,
Jun 29, 2020, 11:45:12 AM6/29/20
to
Well, except that function pointers can be dereferenced. My fault, I
forgot the middle word in "dereferencable object pointer". Or, maybe one
can say and write that, but to me it's more than one mouthful.


> One other point, I thought that a pointer to dynamic memory, once that
> memory was free()ed, could now hold a 'trap value', which is in one
> sense, no longer a 'valid' value, as merely inspecting the value of the
> pointer could terminate your program.

Yeah, but that dangling pointer is not valid.


- Alf

Richard Bos

unread,
Jun 29, 2020, 12:37:44 PM6/29/20
to
Keith Thompson <Keith.S.T...@gmail.com> wrote:

> Bart <b...@freeuk.com> writes:
> [...]
> > The C type system really doesn't help. Looking at just the simplest
> > char* type, this could point to one character (a 0D array), or the
> > first of a sequence (a 1D array of char or a zero-terminated
> > string). With the possibilities with each extra * growing.
>
> A value of type char* points to a single object of type char. [*]
>
> That object may or may not be the initial element of an array object.
>
> Please don't try to make it sound more complicated than it really is.

This.

Please, this.

People (like Bart, but also like so many C++ or Rust or Go or Python or,
Nyarlathotep help us, PHP advocates) pretend that C's handling of
pointers is complicated. It is not. It's only complicated when you
pretend, in your mealy-pap-fed way, that pointers are magical in a way
that they are not. Pointers are straightforward and easy, as long as you
don't pretend that they are "special".

(Great Old Ones, the StackOverPuke questions...)

Richard

Richard Bos

unread,
Jun 29, 2020, 5:59:48 PM6/29/20
to
r...@zedat.fu-berlin.de (Stefan Ram) wrote:

> )=@V Yrkoc36$6* #rl_AG}"53x8]E i&y9R{KmqvqF~
> @Bqv~~o?gx|\<wI!SXOV:^]q+sIjeyi(<H{K-KWm"x/t
> a?<lk?hp?+xtTB,JdG\pU9O'vvFw=d(*7P?i4cW{AYYB
> 1,DCxI8=kU:db\F;*r^9!6hpo,"0#Ja(XK&|+4G(X@N#

You can't fool me. That's not Befunge. This is:

"'.niagA kcaB d"v> v
v$<v"r There an"< >$v
>#| :,: |#<
@>"o ,egnufeB'"^@

Richard
0 new messages