Question about void pointers

K

Keith Thompson

Peter Nilsson said:
How often is this useful? When it is, how useful is %p?

Printing pointer values probably useful very often, but I like having
"%p" for those cases where it is useful.
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?

I must admit I've used *printf and *scanf to print and reconstitute a
pointer value. But with reasonable precautions, such as printing the
value at the end of a line with something recognizable in front of it,
I wouldn't have any qualms about assuming that the output format will
be reasonable. A new-line character in the middle of the result would
mess this up, but I'm content to count on vendors not to do something
that silly.
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?

There's no actual guarantee of this, but again, I'm willing to assume
reasonable behavior. Having the output of "%p" exceed the maximum
text line length is hardly the only silly but legal thing a perverse
implementation could do.
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++);
}

Sure, that works too. On the other hand, on some systems it's
traditional to show addresses in octal rather than in hexadecimal; on
others, address might be segmented, and your method loses the
distinction between the discrete pieces of the address, something that
"%p" would probably capture.

And it prints the bytes backwards on a little-endian system.

Also, if two different representations represent the same address
(possible in a segmented addressing system), "%p" could at least
potentially normalize them.
 
K

Keith Thompson

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

You know what? This most recent statement of yours:

In the greater majority of cases x will incremented REGARDLESS of
whether it was initialised or not.

is one that I agree with.

So what's your problem?

Read the quoted material above. vippstar made a perfectly correct
statement, that x will be incremented if it's been initialized
(leaving aside for the moment the question of whether it's incremented
by 1 or by 4). Expanding that statement to cover the case where x has
not been initialized would have required, for accuracy, a discussion
of undefined behavior, trap representations, and all that stuff. He
quite reasonably chose not to open that can of worms.

You responded by claiming, without qualification, that x will be
incremented even it hasn't been initialized. You've now backed off
from that statement with your "greater majority of cases"
qualification, but you refuse to acknowledge that your more recent
statement differs from your earlier one.
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.

I'm glad to hear it -- and a bit surprised, given that many of your
earlier statements in this thread did not demonstrate such knowledge.

Please try to understand that your earlier claim that:

Even if it wasnt initialised it would be incremented by something.

could easily mislead an unwary newbie into thinking that it's safe to
increment an uninitialized pointer.

In addition, your later statement:

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

is correct, but it could lead someone to the incorrect conclusion that
someone had actually written "it will not increment".

You might think that putting words into other people's mouths makes it
easy to win arguments, but that trick doesn't work so well when
people's actual words are recorded.
 
B

Barry Schwarz

I see, got to switch to char * so that it can be incremented properly.

If you cast b to int* then the expression could be simpler:
b = ((int *)b) + 5;

Any pointer to a complete type can be used for pointer arithmetic.
Yes, but by using the offsetof() macro in <stddef.h>

I meant to point to the structure.

struct st { int val; } a[100];

void *b;

a[5].val = 100;

b = a;
b = ((unsigned char *)b) + 5 * sizeof *a;

printf( "%d\n" , b->val );

Why don't you just run it through your compiler and note the mandatory
diagnostic? The left operand of -> must be a pointer to struct. While
b has the correct value, does it have the correct type?
 
J

Jean-Marc Bourguet

@type pvoid.c
#include <stdio.h>

int main()
{
int x;
char y;
char t[10];
int i;
printf("&x = %p\n&x = %o\n&y = %p\n", (void*)&x, (unsigned)&x, (void*)&y);
for (i=0; i<10; ++i) {
printf("&t[%d] = %p\n", i, &t);
}
return 0;}


I'm curious, why don't you cast &t to (void *)?


I just forgot it as I normally don't make a difference between char* and
other pointers and always cast when passing them to variadic functions (see
for y above). But, while I haven't the time to back up my opinion with
citations, I also think that it shouldn't make a difference for that
reason:
My thoughts: &t is a char *. void * and char * are guaranteed to
have the same representation and size.
However, does that let you pass char * to a variadic function
expecting void *? (there's probably not a singlest implementation
where it'd matter, but I'm curious)


I think so.

Yours,
 
O

Owen Jacobson

Another interesting question is why there's no format for printing
function pointers

I would assume that, due to the existence of dynamic loading and
relocatable libraries, you can't realistically enforce that the
printable representation of a function pointer, when fed to scanf,
reconstitutes that function pointer.

Sure, it can be *done*, but making every implementation do it is
pretty far out of line.

-o
 
K

Keith Thompson

Owen Jacobson said:
I would assume that, due to the existence of dynamic loading and
relocatable libraries, you can't realistically enforce that the
printable representation of a function pointer, when fed to scanf,
reconstitutes that function pointer.

Sure, it can be *done*, but making every implementation do it is
pretty far out of line.

I don't think that's the issue. Pointer values are only expected to
be valid within the current execution of the current program. Within
that context, you can already save the representation of a function
pointer (say, by treating it as an array of unsigned char and getting
a hexadecimal representation) and then later reconstitute the pointer
value, and it will work. A printf format for function pointers
wouldn't create any new problems.

I think it's just a matter of insufficient demand.
 
N

Nick Keighley


note this

there is a *well defined* and *portable* way to do this. So why choose
a non-portable way? I'm sorry I've had this sort of argument before
(in my work place) we really are on different planets. Why NOT
use a portable means, if it exists?


so now you know- so don't do it again

I was referring to the task of performing pointer arithmetic on a void
pointer rather than on an unsigned char pointer, in a case where the
pointer points to some arbitrary object (an array of int, in the OP's
case).

thats the ""worst advice of the month" clc award" referredf to
earlier. He probably thinks somone will come up with something
even more stupid before the end of the month


but he still thinks it's pretty stupid

the americans are having an election. It involves a process
called "choosing a running mate". He was making a half-humerous
reference to this.

Note: comp.lang .c doesn't have a "worst advice of the month award"
(perhaps it should)


I hope I helped you there
...says someone who made a remark about something without being aware
of what he was talking about.
que?

Seriously, though, I don't know what you
mean by me "being on the ballot a couple of weeks from now" or me
"choosing my running mate yet."


--
Nick Keighley

"an easy to use computer should do what I mean, not what I say,
and by no means send me a dancing paper clip to ask"
Nicholas Negroponte (MIT Professor)
 
N

Nick Keighley

My pointers were numbers. I could see them in the debugger....- Hide quoted text -

but in general they aren't. Think DOS. Think IBM mainframe.
Are you trying to be dense?
 
N

Nick Keighley

to print pointer representations...

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.]

I've used it to identify objects. The one thing that is unique
is the address!! For instance to track memory leaks. A log
kept track of when things were allocated and freed (and some
other history). You then had a fighting chance of working
out why things were not freed. Note this would work whatever
representation %p used.

--
Nick Keighley

"Morality is a spandrel of the game theoretic implications of the
society of symbol users.
We impute moral worth to the non-social world on that basis."
(John Wilkins talk.origins)
 
R

Richard

Ben Bacarisse said:
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.

Hold on here. You're trying to be smart. Once again

1) I do not think that incrementing a non initialised var is a good
idea.
2) Yes I know the standard says "UDB".
3) In ALL cases I have ever known it IS incremented.

So to say "it is not incremented" is not true.

We can play all the word games you like. But the above are true.
Ah, you do it seems. That is not what the standard says. It says

Do you have a comprehension issue today? I am not supporting that
increment. I am not saying one should do it. I am not arguing about what
the standard says, I am merely saying that in the real world in the
great majority of cases it is indeed incremented.

Which part of the above confuses you or you trying to manipulate this
into making me look like some clueless nOOb who is not aware of the
dangers of toying with UDB?
 
R

Richard

Nick Keighley said:
but in general they aren't. Think DOS. Think IBM mainframe.
Are you trying to be dense?

Are you?

What pointer do you know that doesnt render as a number? MSDOS,
anything. I have built various SW systems on various machines and am yet
to see a pointer which did not correspond to a memory address. And lets
face it that address IS a number whether you like to be too clever about
it or not.

--
 
V

vippstar

What pointer do you know that doesnt render as a number? MSDOS,
anything. I have built various SW systems on various machines and am yet
to see a pointer which did not correspond to a memory address. And lets
face it that address IS a number whether you like to be too clever about
it or not.

You are wrong. Pointers are objects. Objects have a representation,
which is a bit string.
Bit strings can interpreted in arbitrary ways. One of them is treating
the bit string as a base 2 integer.

I'm sure you'll come up again with something stupid to say. Don't let
me down.
 
R

Robert Gamble

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.

You're missing the point, void * and char * are guaranteed to have the
same representation, I haven't seen anyone else say otherwise, and the
accepted solution involves converting back and forth through
(unsigned) char *. The problem is that since the Standard expressly
forbids pointer arithmetic on void * pointers (despite similarities
with char pointers, they are a different type), many compilers do not
support it and those that do cannot support it in full compliance
mode. The objection stems from the issue of portability, especially
given that there is a simple, portable alternative.
 
V

vippstar

On Sep 16, 7:00 pm, Antoninus Twink <[email protected]> wrote:

[snip incrementing void pointers]
You're missing the point, void * and char * are guaranteed to have the
same representation, I haven't seen anyone else say otherwise, and the
accepted solution involves converting back and forth through
(unsigned) char *. The problem is that since the Standard expressly
forbids pointer arithmetic on void * pointers (despite similarities
with char pointers, they are a different type), many compilers do not
support it and those that do cannot support it in full compliance
mode. The objection stems from the issue of portability, especially
given that there is a simple, portable alternative.

Well, that is not entirely true. It's possible for a compiler to
support [*] incrementing void * pointers in strict conformance mode.
Incrementing a void pointer is a constraint violation which, as far as
the standard is concerned, requires a diagnostic.
The compiler may, along with emitting that diagnostic, choose to
increment the pointer as if it were a char * pointer.

[*] support as in, choose a particular behavior when undefined
behavior is invoked.
 
C

Chris Dollin

Richard said:
What pointer do you know that doesnt render as a number? MSDOS,
anything. I have built various SW systems on various machines and am yet
to see a pointer which did not correspond to a memory address.

Clearly a pointer has to "correspond" with a "memory address" in some
way, otherwise you couldn't use it to access memory.
And lets face it that address IS a number whether you like to be
too clever about it or not.

/Part of/ an address has to respect arithmetic, at least + - = < >.
That doesn't mean the address /is/ a number. One only has to remember
segmented addresses to realise that.
 
B

Ben Bacarisse

Richard said:
Hold on here. You're trying to be smart. Once again

1) I do not think that incrementing a non initialised var is a good
idea.
2) Yes I know the standard says "UDB".
3) In ALL cases I have ever known it IS incremented.

So to say "it is not incremented" is not true.

We can play all the word games you like. But the above are true.


Do you have a comprehension issue today?

No, but I can see there no point in continuing. We have both made our
positions clear.
 
J

James Kuyper

Richard wrote:
....
3) In ALL cases I have ever known it IS incremented.

How is that relevant? You clearly do not know ALL cases, since there are
real machines (one has already been cited) where it is NOT incremented.
The existence of that machine (and many others with similar properties)
is far more relevant than your lack of experience with such machines.
So to say "it is not incremented" is not true.

No one but you has said anything like that, and you have said it only to
refute the claim (which no one made). What has been said is that your
claim that it is incremented is not always true.

....
the standard says, I am merely saying that in the real world in the
great majority of cases it is indeed incremented.

And if you had qualified your original statement with "in the great
majority of cases", it would have been unobjectionable. It was your flat
out, unqualified assertion that it is incremented that people have been
objecting to.
Which part of the above confuses you or you trying to manipulate this
into making me look like some clueless nOOb who is not aware of the
dangers of toying with UDB?

You don't look like a clueless nOOb. A nOOb has too little experience,
and is generally very aware of that fact. You look like someone who has
too much experience with a limited class of machines, and as a result
tends to assume that all machines are like the ones you have experience
with, or at least all machines worth bothering to think about.
 
R

Richard

Ben Bacarisse said:
No, but I can see there no point in continuing. We have both made our
positions clear.

Actually,no, you haven't. You keep trying to put words in my mouth. I am
surprised. My comments are clear enough.
 
R

Richard

Chris Dollin said:
Clearly a pointer has to "correspond" with a "memory address" in some
way, otherwise you couldn't use it to access memory.


/Part of/ an address has to respect arithmetic, at least + - = < >.
That doesn't mean the address /is/ a number. One only has to remember
segmented addresses to realise that.

So, you are saying that in segmented architectures (which I wrote
assembler VGA libraries for) your debugger does not store the pointer
parts in binary registers which in turn render as numbers on the
debugger display?

Now this is getting silly.

My only comment was that in most cases an uninitialised pointer will
indeed increment in the real world.

nothing more. Nothing less.

Quite why this has turned into a crusade for clc standard correctness is
any ones guess.
 
R

Richard

You are wrong. Pointers are objects. Objects have a representation,

No. I am not wrong. Did you not see "render" there?
which is a bit string.

And a bit string can, through the wonders of modern CS, be interpreted
as a number. A physical address.
Bit strings can interpreted in arbitrary ways. One of them is treating
the bit string as a base 2 integer.

Err yes. I know. Probably better than you.
I'm sure you'll come up again with something stupid to say. Don't let
me down.

You are an ignorant clown at times.

I showed the code. I showed the results. You can spin it whichever you
want to.

The end result is that the pointer is incremented in
99.99999999999999999% of systems out there initialised or not.

Which part confuses you other than your mad desire to be an anal
retentive fool who can not match the standard to the real world?
 

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,226
Latest member
KristanTal

Latest Threads

Top