Question about void pointers

C

CBFalconer

.... snip ...

I think Bus Error,on some machines, is one of those consequences.
Thanks all for gcc info. I thought gcc didn't take anything as
stride value for void pointers

Its a non-standard extension. Use of -ansi -pedantic will shut it
off, and make gcc a standard conforming compiler. Advisable to add
-W -Wall.
 
R

Richard

CBFalconer said:
Richard said:
[snip]

You're using "%u" to print pointer values. Surely you know that
invokes undefined behavior, and I know of common real-world systems

Garbage. On my machine it prints a 32 bit value. Pointers are values
which I can printf and see and they correspond to physical memory
locations. Its a number get over it.

Then why does printf have a "%p" format?

Pointers are not numbers. They are often, but not always, implemented
as numbers, but they are different things. If you don't understand
the difference, you don't understand C; at best, you might have some
understanding of a particular C implementation.

Actually quite a few. I challenge you to find me ONE single
implementation where a pointer is not an integer (no size specified)
value when displayed in a debugger. Do TRY and be realistic. No wonder
so many people think pointers are difficult if you are teaching
them. However some of us reside in the real world.

Piggy-backing, because Richard is PLONKed here. However this post
is full of misinformation.

It sure is. Why do you do it?
There are lots of such implementations, such as anything that runs
under MsDOS. All malloc has to do is find some place to store
information. This may involve selecting a school, a grade, and a
small boy within that grade to hold a piece of paper. The pointer

But you cant name one that does that.
will contain the information about school, grade, small boy, and
which piece of paper. malloc allocates storage, not necessarily
conventional memory.

Malloc allocates storage. It returns a pointer. To memory. Withing the
bounds of virtual memory.

No wonder half of you have never managed to teach anyone what pointers
are if you constantly try to make it more complicated than it is.
 
A

Antoninus Twink

In gcc you can perform arithmetic on void pointers as it assumes
unsigned char *. Which is common sense IMO in 99.9999% of platforms
since real memory is address at real memory addresses which are real
numbers.

It's another clc obsession, though. void* and char* can be losslessly
converted back and forth. Nonetheless, /in theory/ they can have
different representations. The fact that they don't on any system in
existence or any system that will ever be built doesn't stop the "regs"
waking up in a cold sweat worrying about it.

It would merely be tragic if they didn't go to such lengths to confuse C
newbies with this and other idiotic angels-on-the-head-of-a-pin debates.
 
A

Antoninus Twink

There are lots of such implementations, such as anything that runs
under MsDOS. All malloc has to do is find some place to store
information. This may involve selecting a school, a grade, and a
small boy within that grade to hold a piece of paper. The pointer
will contain the information about school, grade, small boy, and
which piece of paper.

Is it possible that your memory of MS-DOS has become fuzzied over time?
I mean, I know it was a primitive OS, but really...
 
A

Antoninus Twink

If x isn't initialized, referring to its value invokes undefined
behavior. It's possible, on some systems, that x could have a value
such that attempting to read it causes a program crash. (Before you
ask, no, I don't have an example.)

Well, what a surprise!

Just as long as you don't let that horrible, messy thing called reality
get in the way of the simple purity of the Abstract ISO C Machine.
 
K

Keith Thompson

Antoninus Twink said:
void* and char* can be losslessly
converted back and forth. Nonetheless, /in theory/ they can have
different representations.
[...]

Wrong.
 
C

CBFalconer

Peter said:
That's actually a very good question! If you ever hear
a good answer, please share it.

Well, how about "to allow printf to output a printable char
representation of a void* pointer, readable by scanf to
reconstitute that pointer".
 
A

Antoninus Twink

C89, 3.1.2.5, and C99, 6.2.5(26): "A pointer to void shall have the same
representation and alignment requirements as a pointer to a character
type."

Well, great.

CBF says something is a problem in practise. I point out that it's at
worst a problem in theory. And actually it isn't even that.

It seems that the ISO C committee have a bit more common sense than the
average clc regular in these matters.
 
K

Keith Thompson

Peter Nilsson said:
That's actually a very good question! If you ever hear
a good answer, please share it.

I'm not sure of the basis for your question. Do you mean to imply
that "%p" isn't useful? If so, are you suggesting the use of other
existing formats, or questioning the need to print pointer values in
the first place?

Another interesting question is why there's no format for printing
function pointers; I suspect the answer is that it wasn't thought to
be sufficiently useful. On many systems, casting to void* and using
"%p" works; more generally, you can always get at the representation
as an array of unsigned char and print it in, say, hexadecimal.
 
B

Ben Bacarisse

Richard said:
Even if it wasnt initialised it would be incremented by something.

This thread has gone off in another direction, but I want to come back
to this. Please, coders of the world, don't take this remark from
Richard to heart -- think of your children!

We are currently living though an particularly stable few decades in
terms of machine architecture, but it was not always so and may not
always be so in the future. A large body of C code that plays fast
and loose with indeterminate pointers, treating pointers as if they
were numbers into a flat value space, or assumes that casts (on
pointers) don't change values will condemn future generations to one
of two fates:

(a) All CPU's look more and more alike and none do anything clever
with the address space because that valuable body of code won't work
without massive porting effort; or

(b) A future generation of rookies (they may be your kids!) has to
wade through all that 25 year old code looking for these bugs.

The serious point is that is does not matter if there are no machines
*now* that trap on the above code or code like

int a[1], *ap = a; a--;

there were such machine once and I, for one, would like to think there
might be again. At the very least, are you /sure/ you know exactly
which undefined behaviours will still work in 25 years time?

[Aside: Do your own thought experiment -- mine goes like this: 25
years ago I worked for a large computer company in a office with no
network. They wanted me to implement a protocol whose name I now
forget because they did not think this TCP/IP stuff would take off. I
was sent off to see a competitor that had just stared to export to the
UK to see if their 68000-based systems were any good (the then tiny
Sun Microsystems). I did not see an Ethernet until the next year --
it was a fat yellow cable that could not take tight bends but it did
run at 1M bit and you could get an interface card for only £500.
There were no laptops and PCs were a joke. Graphical interfaces were
just breaking out the research lab.]
 
R

Richard

Ben Bacarisse said:
This thread has gone off in another direction, but I want to come back
to this. Please, coders of the world, don't take this remark from
Richard to heart -- think of your children!

Oh for goodness sake Ben, I was not condoning it! But to say "it will
not increment" is clearly false.
 
P

Peter Nilsson

CBFalconer said:
Well, how about "to allow printf to output a printable char
representation of a void* pointer,

How often is this useful? When it is, how useful is %p?
readable by scanf to reconstitute that pointer".

Having printed a pointer with %p, how does a program guarantee
that subsequent printed characters will not undermine scanf's
ability to reconstitute a comprable pointer value?

If I do something like...

printf("ptr is %p\n", (void *) ptr);

....what is the guarantee that the output won't exceed an
implementation's limit on text line width?

When I do print pointers, I hex dump the representation.
It's the only way to gain full control over the output.

#include <stdio.h>
#include <limits.h>

#define CHAR_NIBBLE ((CHAR_BIT + 3) / 4)

void dump_ptr(FILE *fp, const void *ptr)
{
const unsigned char *p = (const unsigned char *) &ptr;
size_t i;
for (i = 0; i < sizeof ptr; i++)
fprintf(fp, "%0*X", CHAR_NIBBLE, (unsigned) *p++);
}
 
P

Peter Nilsson

Richard Heathfield said:
Peter Nilsson said:

Implementations have considerable licence over the textual
representation of pointer values.

That's the problem.
One MS-DOS compiler I have used (dim and distant past,
admittedly) would print pointer values like this: DS:FADE
I mean *obviously* that's a number, right? It's just not
immediately obvious /which/ number it is.

In the rare cases where I print pointers, I'm less concerned
about the pointer value itself than I am about how the value
is displayed.

Realising this, I've often asked myself why I bothered
printing the pointer in the first place! Which brings us
back to the question of why %p exists. [And why, if it is
to exist, is there no corresponding specifier for function
pointers.]
 
B

Ben Bacarisse

Richard said:
Oh for goodness sake Ben, I was not condoning it! But to say "it will
not increment" is clearly false.

Why? I honestly can't see why you think it must do anything at all.

The whole point of my post was to say "beware" to people who
mock undefined behaviour because you don't know the future. On the
Cambridge CAP machine, that code would terminate the program before
the increment. In fact, 'int *x; x;' could terminate the program if the
compiler did not optimise the reference to x away. Do you know that
the code will increment on every future machine, now that this awkward
old one is so much scrap?
 
K

Keith Thompson

Richard Heathfield said:
Keith Thompson said: [...]

Well, obviously. Look at the source.

Nevertheless, incredible as it may seem, some people might not realise even
now that the source is unreliable, so here's C&V from both Standards (the
wording is identical in each):

C89, 3.1.2.5, and C99, 6.2.5(26): "A pointer to void shall have the same
representation and alignment requirements as a pointer to a character
type."

This originated with an attempt by one of the trolls to refute a
statement that CBFalconer never actually made, in contrast to the
perfectly correct statement that he did make.

The language requires void* and char* to have the same
representation, but it does not allow pointer arithmetic on void*
(Chuck made the latter statement). More precisely, any attempt
to perform such arithmetic is a constraint violation, requiring
a diagnostic.

The whole point of having void* in the language is that it
doesn't point to any specific type. Allowing arithmetic on
void* as an extension, as if it pointed to a one-byte object,
weakens that distinction for the sake of some minor convenience.
(A side effect of the way this extension is implemented is that,
absurdly, sizeof(void)==1.)
 
R

Richard

Ben Bacarisse said:
Why? I honestly can't see why you think it must do anything at all.

I dont think it *must* do anything at all. But I am yet to see a machine
where it is not incremented if it is not initialised. Its
"uninitialised" value is incremented in each and every case. Sure its
"undefined behaviour in terms of the value, but its still UDV+1 ...
The whole point of my post was to say "beware" to people who
mock undefined behaviour because you don't know the future. On the

Let me make something very clear - I am not mocking UDB. I am just
pointing out that in most cases it is WRONG to say the unitialised
variable is NOT incremented. It is. In nearly all cases and certainly in
EVERY case I have worked on on various common machines.
Cambridge CAP machine, that code would terminate the program before
the increment. In fact, 'int *x; x;' could terminate the program if the
compiler did not optimise the reference to x away. Do you know that
the code will increment on every future machine, now that this awkward
old one is so much scrap?




--
 
K

Keith Thompson

Richard said:
Oh for goodness sake Ben, I was not condoning it! But to say "it will
not increment" is clearly false.

And who exactly said "it will not increment"?

vippstar's actual statement, which you quoted, was:

"... assuming x was initialized, it would be incremented by 1".

He quite reasonably chose not to make any claim about what would
happen if x was not initialized.
 
R

Richard

Keith Thompson said:
And who exactly said "it will not increment"?

vippstar's actual statement, which you quoted, was:

"... assuming x was initialized, it would be incremented by 1".

He quite reasonably chose not to make any claim about what would
happen if x was not initialized.

Can you be more obstinate and childish? There is nothing "reasonable"
about it all in the context of which I am talking. In the greater
majority of cases x will incremented REGARDLESS of whether it was
initialised or not. Why this is so tricky for you to understand I am not
sure. You seem unable to think outside of the standard. Do try.

Yes, yes demons out of noses etc etc. But meanwhile in the real world.


And ONCE AGAIN : yes I DO understand that incrementing an uninitialised
variable is a silly thing to do.
 
B

Ben Bacarisse

Richard said:
I dont think it *must* do anything at all.

Good. We are agreed. I can't see how your "even if it wasn't
initialised it would be incremented by something" is consistent with
that because it suggests at least one thing must happen -- some form
of increment -- but it seems you don't hold that view any more.
But I am yet to see a machine
where it is not incremented if it is not initialised. Its
"uninitialised" value is incremented in each and every case. Sure its
"undefined behaviour in terms of the value, but its still UDV+1 ...

Ah, you do it seems. That is not what the standard says. It says
that the value may be a trap representation and that accessing such a
thing in the normal way is undefined. At that point (which can be
before the increment) the program may terminate or do whatever your
favourite example of UB is. I think termination is undefined enough
and is what the machine I described would do.
Let me make something very clear - I am not mocking UDB. I am just
pointing out that in most cases it is WRONG to say the unitialised
variable is NOT incremented.

I did not say it is *not* incremented -- you said it *will* be and at
the time you gave no exceptions.

The standard says it may not be and think you have missed that
possibility. Pointers can be invalid in such a way that merely
"touching" them cause a fault. This is an excellent bit of standards
writing and allows C to be implemented on machines with very strict
address checking in hardware (such as the CAP).
It is. In nearly all cases and certainly in
EVERY case I have worked on on various common machines.

I would never have posted if you had said "even uninitialised, it will
usually be incremented". You agree the undefined behaviour is
important but rather than point out that the example has undefined
behaviour you just chose to say what usually happens on current
machines. That does not add to the general readers stock of
understanding.
 

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
473,777
Messages
2,569,604
Members
45,218
Latest member
JolieDenha

Latest Threads

Top