469,293 Members | 1,319 Online
Bytes | Developer Community
New Post

Home Posts Topics Members FAQ

Post your question to a community of 469,293 developers. It's quick & easy.

Question about void pointers

Is this valid?

int a[20];
void *b;

b = (void *)a; // b points to a[0]

b += 5*sizeof(*a); // b points to a[5]

a[5] = 100;

printf( "%d\n" , *((int *)b) ); // prints 100

If so, if a had been a struct, would it still work?

Is there a possibility that the array could contain some padding, so
rather than sizeof, the assignment would be

b += 5*( (void *)(&(a[1])) - (void *)(&(a[0]));

which seems more more complex.

Would any padding be incorporated into sizeof anyway?
Sep 16 '08
160 4569
Richard<rg****@gmail.comwrites:
Ben Bacarisse <be********@bsb.me.ukwrites:
[...]
>>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.
Yes, the above are true.

But nobody said "it is not incremented", or even words to that effect.
You are refuting a claim that nobody ever made.

[...]
>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.
Putting words in *your* mouth? Typical trollish hypocricy. I'm
tempted to assume that you're doing it deliberately, but I really
don't care one way or the other.

--
Keith Thompson (The_Other_Keith) ks***@mib.org <http://www.ghoti.net/~kst>
Nokia
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
Sep 17 '08 #101
On Sep 17, 6:51 pm, Keith Thompson <ks...@mib.orgwrote:
Eric Sosman <Eric.Sos...@sun.comwrites:

[...] Also, FWIW, although I've used "%p" with printf() I have
never found a reason to use it with scanf(). Pleasant symmetry,
I suppose (although printf() and scanf() are by no means mirror
images), but I've never found a use for it.

[...]

I've never used it either, but I can think of a plausible use for it.

Programs X and Y communicate with each other somehow. They could be
running on the same machine, on different machines, whatever.
They should however, use the same implementation.
Else program X's %p is/might be different than Y's.

I remember someone, some months ago, saying he once had to write
pointers to files, or perhaps he was just describing a scenario where
this might happend.
Sep 17 '08 #102
On Sep 17, 6:40 pm, s0s...@gmail.com wrote:
On Sep 17, 10:22 am, vipps...@gmail.com wrote:
On Sep 17, 5:55 pm, s0s...@gmail.com wrote:
[about incrementing void pointers as opposed to (char *) cast]
Because sometimes you don't need portability and because sometimes
there's a better way?
Yes, that better way being the portable way, in this case.

Well, it's a matter of whether you prefer void * or char *.
No you idiot, it's a matter of whether you prefer portability over non-
portability without any other gains or loses.
...
Why is it rubbish? If you have a void pointer, it will typically point
to any kind of object: int, double, long long, structures, anything.
Does it seem natural to you to treat such an object as if it were a
*character*?
No it doesn't. How the heck does void * feel more natural to treat as
a pointer to character than char *?

Read again: I was talking about pointers to int, double, long long,
structures, or any arbitrary object. How do you come up with "pointer
to character"?
Read again.
...
Why not? I'll simply keep in mind that it works only under a certain
compiler.
No, what you keep in mind is to never suggest this crap again.

Give me a good argument not to.
Because it's crap. See previous posts to learn why.
P.S. Just a troll or too stubborn?

You have demonstrated several things in this post:

- You have reading comprehension problems
You certainly do.
- You are aggressive about purely stylistic issues
OH MY GOD what an idiot. I'm ignoring you.
- You are incapable of using decent language

It's clear who is the troll here.
True. Bye.
Sep 17 '08 #103
In article <7e**********************************@59g2000hsb.g ooglegroups.com>,
<vi******@gmail.comwrote:
>Programs X and Y communicate with each other somehow. They could be
running on the same machine, on different machines, whatever.
>They should however, use the same implementation.
Else program X's %p is/might be different than Y's.
The second program doesn't have to use %p to read the value, since it
doesn't try to interpret it. Since the %p format only produces
printing characters, a linefeed is sufficient to bound it.

-- Richard
--
Please remember to mention me / in tapes you leave behind.
Sep 17 '08 #104
Robert Gamble wrote:
>
.... snip ...
>
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.
In addition, as far as I can tell, there is no prohibition against
returning void* and char* pointers in different registers (or other
entities). If this is correct, using the interchangeably can
create an ugly code block.

--
[mail]: Chuck F (cbfalconer at maineline dot net)
[page]: <http://cbfalconer.home.att.net>
Try the download section.
Sep 17 '08 #105
On Sep 17, 7:22 pm, rich...@cogsci.ed.ac.uk (Richard Tobin) wrote:
In article <7e9d8535-4028-4e50-bb70-9eac55887...@59g2000hsb.googlegroups.com>,

<vipps...@gmail.comwrote:
Programs X and Y communicate with each other somehow. They could be
running on the same machine, on different machines, whatever.
They should however, use the same implementation.
Else program X's %p is/might be different than Y's.

The second program doesn't have to use %p to read the value, since it
doesn't try to interpret it. Since the %p format only produces
printing characters, a linefeed is sufficient to bound it.
Ah yes, you are right. thanks.
Sep 17 '08 #106
s0****@gmail.com wrote:
On Sep 17, 3:02 am, Nick Keighley <ni******************@hotmail.com>
wrote:
>On 16 Sep, 21:14, s0s...@gmail.com wrote:
....
>>>>>>Besides, void * seems more natural for this kind
>>of task.
rubbish

Why is it rubbish? If you have a void pointer, it will typically point
to any kind of object: int, double, long long, structures, anything.
Does it seem natural to you to treat such an object as if it were a
*character*?
Tracing back, "this kind of task" refers to:

int a[20];
void *b;
b = (void *)a; // b points to a[0]
b += 5*sizeof(*a); // b points to a[5]

In this case, 'b' is being used as a pointer to char, because the amount
that is being added to is a number of bytes, not a number of ints. That
being the case, it should be declared as char*, not void*.

If you want use it as a pointer to int, declare it as such:

b = (int*)b + 5;

That has the advantage of being not only more portable than the
original, but simpler, too.
Sep 17 '08 #107
Richard<rg****@gmail.comwrites:
Chris Dollin <ch**********@hp.comwrites:
>Richard wrote:
[...]
>>My only comment was that in most cases an uninitialised pointer will
indeed increment in the real world.

That's cool, so long as you acknowledge that "most" and don't
confuse it with an "all".

Huh?!?!?!?!

Please quote where I said all. Where I did not qualify with "in my
experience" or "my platforms".
I'm glad you asked.

In the article with message-id
<ga**********@registered.motzarella.org>, available at
<http://groups.google.com/group/comp.lang.c/msg/d4dc17f7d5a2e317>,
you wrote:

| vipps...@gmail.com writes:
| On Sep 16, 7:13 pm, sh.vi...@gmail.com wrote:
| >when you do
| >--char *c; c++; ==c is incremented by 1
| >--long int *x; x++ ==x is incremented by 4.
| Wrong, assuming x was initialized, it would be incremented by 1.
|
|
| Even if it wasnt initialised it would be incremented by something.

At the very end of that article, you did provide a qualification for a
*different* statement:

| The first printf gives me:
|
| 3214862936
|
| And the second:
|
| 3214862940
|
| Now, that is 4. On my machine.

The context for that "On my machine" qualification was a discussion
about whether the pointer is incremented by 1 or by 4, not the
question of whether it's incremented at all.

Your claim that the pointer will be incremented, whether it had been
initialized or not, was unqualified.

--
Keith Thompson (The_Other_Keith) ks***@mib.org <http://www.ghoti.net/~kst>
Nokia
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
Sep 17 '08 #108
CBFalconer <cb********@yahoo.comwrites:
[...]
In addition, as far as I can tell, there is no prohibition against
returning void* and char* pointers in different registers (or other
entities). If this is correct, using the interchangeably can
create an ugly code block.
There is no such prohibition in the normative text of the standard,
but it's suggested in a footnote.

C99 6.2.5p27:

A pointer to void shall have the same representation and alignment
requirements as a pointer to a character type.

And a footnote:

The same representation and alignment requirements are meant to
imply interchangeability as arguments to functions, return values
from functions, and members of unions.

This is an unfortunate flaw in the standard.

--
Keith Thompson (The_Other_Keith) ks***@mib.org <http://www.ghoti.net/~kst>
Nokia
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
Sep 17 '08 #109
On Sep 17, 11:12*am, vi******@gmail.com wrote:
On Sep 17, 6:40 pm, s0s...@gmail.com wrote:
On Sep 17, 10:22 am, vipps...@gmail.com wrote:
On Sep 17, 5:55 pm, s0s...@gmail.com wrote:
[about incrementing void pointers as opposed to (char *) cast]
Because sometimes you don't need portability and because sometimes
there's a better way?
Yes, that better way being the portable way, in this case.
Well, it's a matter of whether you prefer void * or char *.

No you idiot, it's a matter of whether you prefer portability over non-
portability without any other gains or loses.
...
Why is it rubbish? If you have a void pointer, it will typically point
to any kind of object: int, double, long long, structures, anything..
Does it seem natural to you to treat such an object as if it were a
*character*?
No it doesn't. How the heck does void * feel more natural to treat as
a pointer to character than char *?
Read again: I was talking about pointers to int, double, long long,
structures, or any arbitrary object. How do you come up with "pointer
to character"?

Read again.
...
Why not? I'll simply keep in mind that it works only under a certain
compiler.
No, what you keep in mind is to never suggest this crap again.
Give me a good argument not to.

Because it's crap. See previous posts to learn why.
P.S. Just a troll or too stubborn?
You have demonstrated several things in this post:
* - You have reading comprehension problems

You certainly do.
* - You are aggressive about purely stylistic issues

OH MY GOD what an idiot. I'm ignoring you.
* - You are incapable of using decent language
It's clear who is the troll here.

True. Bye.
Amazing. Let this be a lesson to everyone about all we can expect from
our dear "vippstar" here.

Sebastian

Sep 17 '08 #110
Richard wrote:
Chris Dollin <ch**********@hp.comwrites:
>Richard wrote:
....
>>My only comment was that in most cases an uninitialised pointer will
indeed increment in the real world.
That's cool, so long as you acknowledge that "most" and don't
confuse it with an "all".

Huh?!?!?!?!

Please quote where I said all. Where I did not qualify with "in my
experience" or "my platforms".
You really should check to make sure before issuing such a challenge.
You left out all such qualifying phrases in your very first two messages
on the issue:

You wrote:
Date: Tue, 16 Sep 2008 18:43:31 +0200
....
Even if it wasnt initialized it would be incremented by something.
Your assertion contained no qualifiers. It has no "in my experience", no
"on my platform", no "on most platforms". You just flatly assert that
"it would be incremented". Later in that same message, you did use the
phrase "on my machine", but not as a phrase qualifying this assertion.

You also wrote:
Date: Tue, 16 Sep 2008 19:39:26 +0200
....
Whatever. x will be incremented.
Again, you did not qualify your assertion in any way. You just flatly
asserted it. This was in response to, and apparently intended as a
contradiction of, someone pointing out the existence of platforms where
the increment will not occur because loading the address into a register
in preparation to increment it will cause the program to abort before
the increment can occur. Again, later on you did use the phrase "on my
machine", but not as a qualifying phrase that would moderate your assertion.
Sep 17 '08 #111
On Sep 17, 11:55*am, James Kuyper <ja*********@verizon.netwrote:
s0****@gmail.com wrote:
On Sep 17, 3:02 am, Nick Keighley <ni******************@hotmail.com>
wrote:
On 16 Sep, 21:14, s0s...@gmail.com wrote:
...
>>>>>Besides, void * seems more natural for this kind
>of task.
rubbish
Why is it rubbish? If you have a void pointer, it will typically point
to any kind of object: int, double, long long, structures, anything.
Does it seem natural to you to treat such an object as if it were a
*character*?

Tracing back, "this kind of task" refers to:

int a[20];
void *b;
b = (void *)a; *// b points to a[0]
b += 5*sizeof(*a); // b points to a[5]

In this case, 'b' is being used as a pointer to char, because the amount
that is being added to is a number of bytes, not a number of ints. That
being the case, it should be declared as char*, not void*.
Shouldn't it be unsigned char *? Anyway, my argument was that if your
compiler can perform arithmetic with the void *, then go void *, as
you did above.
If you want use it as a pointer to int, declare it as such:

b *= (int*)b + 5;

That has the advantage of being not only more portable than the
original, but simpler, too.
But it will have a different effect when incremented (it will advance
to the next int, say four bytes later) or dereferenced (it fetch a,
say, 32-bit int, rather than an 8-bit char).

Sebastian

Sep 17 '08 #112
Richard wrote:
James Kuyper <ja*********@verizon.netwrites:
>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

Where did I say ALL cases? Please post a link. And it is relevant
because I am telling MY experience.
When you said that you were describing your own experience, and also
when you added qualifying phrases like "on most implementations", then
there was nothing objectionable about those comments (though they were
of debatable relevance - people should be writing code based upon what
the standard guarantees, not based upon what Richard NoLastName has
experienced).

However, you made unqualified assertions about the behavior of such
code. See the last message I posted, on another branch of this
discussion, for precise citations. And that's where the problem lies.
What are you taking about? I never said there were no machines where the
increment DID NOT take place. I countered the argument that was "the
increment will not happen" or words to that affect.
The only time those words, or words to that effect, have been used in
this discussion was when you used them to incorrectly describe what
other people were saying.
>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.

Err, I said that. I made it clear maybe 5 times now.
Yes, and you said it wrong the first 2 times, and have denied ("no more,
no less") that there was any difference between those first 2 times and
the 5 later ones.
>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.

I dont recall ever saying that.
Follow up the two citations in my other message.
Sep 17 '08 #113
s0****@gmail.com writes:
On Sep 17, 11:55*am, James Kuyper <ja*********@verizon.netwrote:
>s0****@gmail.com wrote:
On Sep 17, 3:02 am, Nick Keighley <ni******************@hotmail.com>
wrote:
On 16 Sep, 21:14, s0s...@gmail.com wrote:
...
>>>>>>Besides, void * seems more natural for this kind
>>of task.
rubbish
Why is it rubbish? If you have a void pointer, it will typically point
to any kind of object: int, double, long long, structures, anything.
Does it seem natural to you to treat such an object as if it were a
*character*?

Tracing back, "this kind of task" refers to:

int a[20];
void *b;
b = (void *)a; *// b points to a[0]
b += 5*sizeof(*a); // b points to a[5]

In this case, 'b' is being used as a pointer to char, because the amount
that is being added to is a number of bytes, not a number of ints. That
being the case, it should be declared as char*, not void*.
It depends on what you want to do with it. If you're going to
dereference it to examine the representation of whatever it points to,
then yes, unsigned char* is better than char*. If you're not going to
dereference it, it doesn't matter whether you use char* or unsigned
char*; both have the same stride, 1 byte.

But the use of the expression "5*sizeof(*a)" indicates that the actual
intent is advance the pointer by 5 ints. The type int* will do
exactly that.

It's impossible to tell from the short snippet what the intent is, but
it does nothing that couldn't be done more conveniently, and with less
risk of error, than this:

int a[20];
int *b;
b = a; /* b points to a[0] */
b += 5; /* b points to a[5] */

Maybe there's some reason for b to be a void* rather than an int*, but
it's not evident from what's been posted so far.
Shouldn't it be unsigned char *? Anyway, my argument was that if your
compiler can perform arithmetic with the void *, then go void *, as
you did above.
That advice is questionable, in my opinion, even if you're only
concerned with gcc. But if you're writing code for, for example, the
Linux kernel, which has no pretense of portability to compilers other
than gcc, then I suppose it's not too bad.

The advice is very bad if there's any possibility that the code will
need to be compiled with something other than gcc.

If you have a void* pointer object, and you want to advance it by N
bytes, it is in my opinion *better* to write:

ptr = (char*)ptr + N;

because it's portable, and because it expresses the idea that you're
doing something that doesn't make sense for void*.
>If you want use it as a pointer to int, declare it as such:

b *= (int*)b + 5;

That has the advantage of being not only more portable than the
original, but simpler, too.

But it will have a different effect when incremented (it will advance
to the next int, say four bytes later) or dereferenced (it fetch a,
say, 32-bit int, rather than an 8-bit char).
Of course it will. That's the point. If you're accessing an array of
int, a pointer of type int* is the best way to do it. You *can* use
void* or unsigned char*, but then you have to write additional code
(casting pointers, multiplying offsets by sizeof(int)).

If you need to access the individual bytes of an array of int, then
void* or unsigned char* is better, but that's a fairly unusual
requirement.

If you show us a problem you need to solve, involving an array of int,
for which int* pointers are not adequate, please do so, and we can
discuss the best way to go about it.

--
Keith Thompson (The_Other_Keith) ks***@mib.org <http://www.ghoti.net/~kst>
Nokia
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
Sep 17 '08 #114
s0****@gmail.com wrote:
On Sep 17, 11:55 am, James Kuyper <ja*********@verizon.netwrote:
....
>Tracing back, "this kind of task" refers to:

int a[20];
void *b;
b = (void *)a; // b points to a[0]
b += 5*sizeof(*a); // b points to a[5]

In this case, 'b' is being used as a pointer to char, because the amount
that is being added to is a number of bytes, not a number of ints. That
being the case, it should be declared as char*, not void*.

Shouldn't it be unsigned char *?
In general, yes. If you need to do byte-based pointer arithmetic,
there's a pretty good chance that sooner or later you'll be using those
pointers to read or write those bytes, and in that case you should be
using unsigned char*. However, in code like this, that only works with
pointers to bytes, without ever dereferencing those pointers, I prefer
'char *', because it requires less typing. In my experience, such cases
don't come up very often.
... Anyway, my argument was that if your
compiler can perform arithmetic with the void *, then go void *, as
you did above.
Please don't say that! I didn't use it - I was quoting code written by
others. I don't want anyone thinking I would write such code.

And I believe, as others have said, that you are giving very bad advice.
There's no good reason not to use char* instead of void*, which would
make your code portable. It's not as if it makes the code any more
complicated. The complication comes only from using void* and repeatedly
converting to and from char*; if you declared is as char* in the first
place, such repetitions could be avoided.
>If you want use it as a pointer to int, declare it as such:

b = (int*)b + 5;

That has the advantage of being not only more portable than the
original, but simpler, too.

But it will have a different effect when incremented (it will advance
to the next int, say four bytes later) or dereferenced (it fetch a,
say, 32-bit int, rather than an 8-bit char).
No, they are exactly identical: (int*)b+5 == b+5*sizeof(int), at least
on the implementations you're talking about that allow the right hand
side as an extension, rather than rejecting the code because it's a
constraint violation. If you think otherwise, you're going to have to
explain why.
Sep 17 '08 #115
s0****@gmail.com wrote:
On Sep 17, 11:55 am, James Kuyper <ja*********@verizon.netwrote:
>[...]
Tracing back, "this kind of task" refers to:

int a[20];
void *b;
b = (void *)a; // b points to a[0]
b += 5*sizeof(*a); // b points to a[5]

In this case, 'b' is being used as a pointer to char, because the amount
that is being added to is a number of bytes, not a number of ints. That
being the case, it should be declared as char*, not void*.

Shouldn't it be unsigned char *?
Why? You've said this at least twice in this thread, but I've
seen no justification. Before you say "trap representation," note
that the pointer (whatever its type) is not dereferenced in this
fragment, and in the original it is dereferenced only after conversion
to int*.
Anyway, my argument was that if your
compiler can perform arithmetic with the void *, then go void *, as
you did above.
Two comments: First, the "do whatever your compiler lets you
get away with" line leads straight back to the pre-Standard chaos.
Would you recommend "#pragma stdio" instead of "#include <stdio.h>"
just because the compiler at hand happens to do something with it?

Second, it wasn't James Kuyper who wrote the misuse of void*;
he was quoting the O.P.'s code.
>If you want use it as a pointer to int, declare it as such:

b = (int*)b + 5;

That has the advantage of being not only more portable than the
original, but simpler, too.

But it will have a different effect when incremented (it will advance
to the next int, say four bytes later) or dereferenced (it fetch a,
say, 32-bit int, rather than an 8-bit char).
It points `b' to the same spot the corrected original did, and
is a cleaner correction. And `b' cannot be dereferenced anyhow, so
the second half of your objection makes no sense.

--
Er*********@sun.com
Sep 17 '08 #116
In article <ga**********@registered.motzarella.org>,
Richard <rg****@gmail.comwrote:
....
>Yes it is. Vippstar is currying favour with the regs. He is obstreperous
to the extreme in his desire to "live and breath the standard".
Indeed. Note that it has yet to be determined exactly whose sock puppet
vippy really is.

Sep 17 '08 #117
On Sep 17, 12:36*pm, Keith Thompson <ks***@mib.orgwrote:
s0****@gmail.com writes:
<snip>
If you want use it as a pointer to int, declare it as such:
b *= (int*)b + 5;
That has the advantage of being not only more portable than the
original, but simpler, too.
But it will have a different effect when incremented (it will advance
to the next int, say four bytes later) or dereferenced (it fetch a,
say, 32-bit int, rather than an 8-bit char).

Of course it will. *That's the point. *If you're accessing an array of
int, a pointer of type int* is the best way to do it. *You *can* use
void* or unsigned char*, but then you have to write additional code
(casting pointers, multiplying offsets by sizeof(int)).

If you need to access the individual bytes of an array of int, then
void* or unsigned char* is better, but that's a fairly unusual
requirement.

If you show us a problem you need to solve, involving an array of int,
for which int* pointers are not adequate, please do so, and we can
discuss the best way to go about it.
Well, I'm not talking specifically about an array of int, but any
arbitrary object. A realistic case where I would find it convenient to
perform arithmetic on a void * is when you have a void * object and
need to call a function that takes a void *. For example, suppose you
have a buffer that you want to append to another buffer:

void *buf1;
void *buf2;
int n, buf2len;
...
memcpy(buf1 + n, buf2, buf2len);

This would append 'buf2' to 'buf1', assuming 'n' is the starting point
of the appending operation. Without being able to perform arithmetic
on the void *, you would have to call memcpy() like this:

memcpy((char *) buf1 + n, buf2, buf2len);

Sebastian

Sep 17 '08 #118
ga*****@shell.xmission.com (Kenny McCormack) writes:
In article <ga**********@registered.motzarella.org>,
Richard <rg****@gmail.comwrote:
...
>>Yes it is. Vippstar is currying favour with the regs. He is obstreperous
to the extreme in his desire to "live and breath the standard".

Indeed. Note that it has yet to be determined exactly whose sock puppet
vippy really is.
Indeed Mr Kenny. Indeed.
Sep 17 '08 #119
In article <ga**********@registered.motzarella.org>,
Richard <rg****@gmail.comwrote:
....
>Quite why this has turned into a crusade for clc standard correctness is
any ones guess.
It's what we do here. Had you not noticed?

Sep 17 '08 #120
s0****@gmail.com wrote:
....
Well, I'm not talking specifically about an array of int, but any
arbitrary object. A realistic case where I would find it convenient to
perform arithmetic on a void * is when you have a void * object and
need to call a function that takes a void *. For example, suppose you
have a buffer that you want to append to another buffer:

void *buf1;
void *buf2;
int n, buf2len;
...
memcpy(buf1 + n, buf2, buf2len);

This would append 'buf2' to 'buf1', assuming 'n' is the starting point
of the appending operation. Without being able to perform arithmetic
on the void *, you would have to call memcpy() like this:

memcpy((char *) buf1 + n, buf2, buf2len);
In the abstract, that looks plausible, but lets get down to details -
why is 'n' measured in bytes? If there's a good reason for it, then that
reason also probably implies that buf1 and buf2 should be pointers to a
character type, not void*. Another possibility is that your code should
have been written so that buf1 already points at the destination of the
memcpy, rather than pointing n bytes earlier. Without a more concrete
example, it's hard to say what the correct design would be, but it's
unlikely to be the one you gave.
Sep 17 '08 #121
s0****@gmail.com writes:
On Sep 17, 12:36*pm, Keith Thompson <ks***@mib.orgwrote:
[...]
>If you show us a problem you need to solve, involving an array of int,
for which int* pointers are not adequate, please do so, and we can
discuss the best way to go about it.

Well, I'm not talking specifically about an array of int, but any
arbitrary object. A realistic case where I would find it convenient to
perform arithmetic on a void * is when you have a void * object and
need to call a function that takes a void *. For example, suppose you
have a buffer that you want to append to another buffer:

void *buf1;
void *buf2;
int n, buf2len;
...
memcpy(buf1 + n, buf2, buf2len);

This would append 'buf2' to 'buf1', assuming 'n' is the starting point
of the appending operation. Without being able to perform arithmetic
on the void *, you would have to call memcpy() like this:

memcpy((char *) buf1 + n, buf2, buf2len);
Which, if you insist on using void*, is exactly what you have to do if
you're using a compiler other than gcc.

Presumably you know the type of the buffer you're pointing to.
Perhaps it's an array of unsigned char. If it is, just declare the
pointers buf1 and buf2 as unsigned char*.

unsigned char *buf1 = /* whatever */;
unsigned char *buf2 = /* whatever */;
int n = /* whatever */;
int buf2len = /* whatever */;
...
memcpy(buf1 + n, buf2, buf2len);

Note that the arguments ``buf1 + n'' and ``buf2'', which in my snippet
are of type unsigned char*, will be implicitly converted to void*.

If you want to point to an object of a certain type, use a pointer to
that type. If you want to point to an object that you're going to
treat as an array of bytes, use unsigned char*. If you want to point
to an object of some arbitrary type and you *don't* need to treat it
as an array of bytes, use void*.

Do you have a more complete and/or convincing example?

--
Keith Thompson (The_Other_Keith) ks***@mib.org <http://www.ghoti.net/~kst>
Nokia
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
Sep 17 '08 #122
On Sep 17, 1:36*pm, James Kuyper <ja*********@verizon.netwrote:
s0****@gmail.com wrote:
Well, I'm not talking specifically about an array of int, but any
arbitrary object. A realistic case where I would find it convenient to
perform arithmetic on a void * is when you have a void * object and
need to call a function that takes a void *. For example, suppose you
have a buffer that you want to append to another buffer:
* * void *buf1;
* * void *buf2;
* * int n, buf2len;
* * ...
* * memcpy(buf1 + n, buf2, buf2len);
This would append 'buf2' to 'buf1', assuming 'n' is the starting point
of the appending operation. Without being able to perform arithmetic
on the void *, you would have to call memcpy() like this:
* * memcpy((char *) buf1 + n, buf2, buf2len);

In the abstract, that looks plausible, but lets get down to details -
why is 'n' measured in bytes?
I guess I just find it natural to relate void pointers with bytes, but
in cases where I don't need to examine the representation of the
bytes. Don't you feel that way too?

Sebastian

Sep 17 '08 #123
On Sep 17, 1:45*pm, Keith Thompson <ks***@mib.orgwrote:
s0****@gmail.com writes:
On Sep 17, 12:36*pm, Keith Thompson <ks***@mib.orgwrote:
[...]
If you show us a problem you need to solve, involving an array of int,
for which int* pointers are not adequate, please do so, and we can
discuss the best way to go about it.
Well, I'm not talking specifically about an array of int, but any
arbitrary object. A realistic case where I would find it convenient to
perform arithmetic on a void * is when you have a void * object and
need to call a function that takes a void *. For example, suppose you
have a buffer that you want to append to another buffer:
* * void *buf1;
* * void *buf2;
* * int n, buf2len;
* * ...
* * memcpy(buf1 + n, buf2, buf2len);
This would append 'buf2' to 'buf1', assuming 'n' is the starting point
of the appending operation. Without being able to perform arithmetic
on the void *, you would have to call memcpy() like this:
* * memcpy((char *) buf1 + n, buf2, buf2len);

Which, if you insist on using void*, is exactly what you have to do if
you're using a compiler other than gcc.

Presumably you know the type of the buffer you're pointing to.
That's an excellent point: what if you _don't_ know what it's really
pointing to? For example, functions such as memcpy(), memmove(),
memset(), etc., are used extensively to deal with objects of any type.
So this functions take void *'s, and they might be pointing to an int,
to a char, to a structure, or anything you can think of. I'm sure the
implementor of such a function would find it enjoyable to be able to
perform void pointer arithmetic!

<snip>

Sebastian

Sep 17 '08 #124
s0****@gmail.com wrote:
On Sep 17, 1:36 pm, James Kuyper <ja*********@verizon.netwrote:
>s0****@gmail.com wrote:
>>Well, I'm not talking specifically about an array of int, but any
arbitrary object. A realistic case where I would find it convenient to
perform arithmetic on a void * is when you have a void * object and
need to call a function that takes a void *. For example, suppose you
have a buffer that you want to append to another buffer:
void *buf1;
void *buf2;
int n, buf2len;
...
memcpy(buf1 + n, buf2, buf2len);
This would append 'buf2' to 'buf1', assuming 'n' is the starting point
of the appending operation. Without being able to perform arithmetic
on the void *, you would have to call memcpy() like this:
memcpy((char *) buf1 + n, buf2, buf2len);
In the abstract, that looks plausible, but lets get down to details -
why is 'n' measured in bytes?

I guess I just find it natural to relate void pointers with bytes, but
in cases where I don't need to examine the representation of the
bytes. Don't you feel that way too?
No, truly I don't. If I want to point at bytes, I use an
`unsigned char*'.

The time to use `void*' is when you don't know what you're
pointing at, when the function can do its job without knowing
or caring about the type of the data it's manipulating. This
usually means one of two things:

1) The function deals with the bytes that represent an object,
not with the object as such. I/O functions, memcpy(),
free(), and so on are type-blind in this sense: They just
care about the object's bytes, not about its nature.

2) The function is a framework operating on "abstracted data
types." It doesn't know what kind of data it's handling,
but it passes the data pointers along to type-specific
functions that do know. qsort() and bsearch() are examples
of this style.

In both cases `void*' is a convenience rather than a necessity,
and C existed for a long time before the convenience appeared. One
could (did) use character pointers where now one uses `void*', and
everything was fine -- except that the function's callers had to
write all those ugly casts:

struct foobar *foo = (struct foobar*)malloc(42 * sizeof *foo);
memset ((char*)foo, 'X', 42 * sizeof *foo);
fwrite ((char*)foo, sizeof *foo, 42, stream);
free ((char*)foo);

.... and so on. (Hoping to suppress a reflex: in C-without-void, the
cast in the first line *is* necessary.) The existence of `void*' --
in particular, its ability to convert to and from other data pointer
types without casting -- allows all that uglification to disappear.
True, for functions of type (1) it probably adds a conversion inside
the function -- but since the usual reason for writing a function
once is to be able to call it from N different places, there's a net
decrease in casting.

To summarize: If you know you're dealing with objects of type T,
use a `T*' -- this is the cleanest and safest option, when available.
If you intend to deal with bytes use `unsigned char*'. If you don't
care what you're dealing with, or if you want to deal with bytes but
want to relieve your callers of casting, use `void*'.

--
Er*********@sun.com
Sep 17 '08 #125
s0s...@gmail.com wrote:
On Sep 17, 1:36�pm, James Kuyper <ja*********@verizon.netwrote:
s0****@gmail.com wrote:
....
In the abstract, that looks plausible, but lets get down to details -
why is 'n' measured in bytes?

I guess I just find it natural to relate void pointers with bytes, but
in cases where I don't need to examine the representation of the
bytes. Don't you feel that way too?
No - i relate void pointers to objects of unknown size, not bytes.
For me, the natural form to use when talking about bytes is unsigned
char*, not void*.
Sep 17 '08 #126
s0s...@gmail.com wrote:
....
pointing to? For example, functions such as memcpy(), memmove(),
memset(), etc., are used extensively to deal with objects of any type.
So this functions take void *'s, and they might be pointing to an int,
to a char, to a structure, or anything you can think of. I'm sure the
implementor of such a function would find it enjoyable to be able to
perform void pointer arithmetic!
I would expect the implementation to be in assembly language. One of
the key reasons why those functions are standardized is that on most
platforms there's a lot of room for improvement if the routine is hand-
assembled rather than compiled from C source code.

Keep in mind that the standard defines the behavior of these functions
in terms of actions on an array of unsigned char. It seems quite
natural to me that, if an implementor chooses to implement one of
those routines using C code, that the code would convert the
parameters into unsgned char* before making any use of them. That's
precisely what I would recommend that you do on any comparable routine
that takes a void* pointer and a byte count as arguments.
Sep 17 '08 #127
On Sep 17, 2:24*pm, Eric Sosman <Er*********@sun.comwrote:
s0****@gmail.com wrote:
>On Sep 17, 1:36 pm, James Kuyper <ja*********@verizon.netwrote:
>>s0****@gmail.com wrote:
Well, I'm not talking specifically about an array of int, but any
arbitrary object. A realistic case where I would find it convenient to
perform arithmetic on a void * is when you have a void * object and
need to call a function that takes a void *. For example, suppose you
have a buffer that you want to append to another buffer:
* * void *buf1;
* * void *buf2;
* * int n, buf2len;
* * ...
* * memcpy(buf1 + n, buf2, buf2len);
This would append 'buf2' to 'buf1', assuming 'n' is the starting point
of the appending operation. Without being able to perform arithmetic
on the void *, you would have to call memcpy() like this:
* * memcpy((char *) buf1 + n, buf2, buf2len);
In the abstract, that looks plausible, but lets get down to details -
why is 'n' measured in bytes?
>I guess I just find it natural to relate void pointers with bytes, but
in cases where I don't need to examine the representation of the
bytes. Don't you feel that way too?

* * *No, truly I don't. *If I want to point at bytes, I use an
`unsigned char*'.
(It seems you're referring to the other kinds of bytes; see below.)
* * *The time to use `void*' is when you don't know what you're
pointing at, when the function can do its job without knowing
or caring about the type of the data it's manipulating. *This
usually means one of two things:

* * *1) The function deals with the bytes that represent an object,
* * * * not with the object as such. *I/O functions, memcpy(),
* * * * free(), and so on are type-blind in this sense: They just
* * * * care about the object's bytes, not about its nature.
Exactly, that's the "bytes" I was referring to. The word "bytes" is
also used to refer to characters. But I was referring to the bytes
that constitute an arbitrary object: int, double, struct, etc., and
that if examined, they will appear to have meaningless values. This is
also why I find it more natural to use void *: you aren't going to
examine what it points to, because all you're going to see are some
arbitrary bits that constitute an object of (possibly) bigger size.

Sebastian

Sep 17 '08 #128
s0****@gmail.com writes:
On Sep 17, 2:24*pm, Eric Sosman <Er*********@sun.comwrote:
[...]
>* * *1) The function deals with the bytes that represent an object,
* * * * not with the object as such. *I/O functions, memcpy(),
* * * * free(), and so on are type-blind in this sense: They just
* * * * care about the object's bytes, not about its nature.

Exactly, that's the "bytes" I was referring to. The word "bytes" is
also used to refer to characters. But I was referring to the bytes
that constitute an arbitrary object: int, double, struct, etc., and
that if examined, they will appear to have meaningless values. This is
also why I find it more natural to use void *: you aren't going to
examine what it points to, because all you're going to see are some
arbitrary bits that constitute an object of (possibly) bigger size.
unsigned char is used for both kinds of "bytes".

--
Keith Thompson (The_Other_Keith) ks***@mib.org <http://www.ghoti.net/~kst>
Nokia
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
Sep 17 '08 #129
s0****@gmail.com wrote:
Nick Keighley <ni******************@hotmail.comwrote:
.... big snip ...
>
>so now you know- so don't do it again

Why not? I'll simply keep in mind that it works only under a
certain compiler.
Because, if you do it properly, you will never have to rewrite it
again. Laziness pays. Whatever 'it' is.

--
[mail]: Chuck F (cbfalconer at maineline dot net)
[page]: <http://cbfalconer.home.att.net>
Try the download section.
Sep 18 '08 #130
vi******@gmail.com wrote:
s0s...@gmail.com wrote:
>vipps...@gmail.com wrote:
>>s0s...@gmail.com wrote:

[about incrementing void pointers as opposed to (char *) cast]

Because sometimes you don't need portability and because
sometimes there's a better way?

Yes, that better way being the portable way, in this case.

Well, it's a matter of whether you prefer void * or char *.

No you idiot, it's a matter of whether you prefer portability
over non-portability without any other gains or loses.
The point being that you can't increment a void* pointer in a
conformant C system. If you (sOs) look at the code generated you
will see that a cast to char* generates none, as does the cast back
to char*. However it clues the compiler in to what is going on.

--
[mail]: Chuck F (cbfalconer at maineline dot net)
[page]: <http://cbfalconer.home.att.net>
Try the download section.
Sep 18 '08 #131
s0****@gmail.com wrote:
>
.... snip ...
>
Shouldn't it be unsigned char *? Anyway, my argument was that if
your compiler can perform arithmetic with the void *, then go
void *, as you did above.
Because a compiler can't 'perform arithmetic with the void*'. It
says so, right in the C standard. Trying to do so results in
undefined behaviour.

--
[mail]: Chuck F (cbfalconer at maineline dot net)
[page]: <http://cbfalconer.home.att.net>
Try the download section.
Sep 18 '08 #132
CBFalconer said:
s0****@gmail.com wrote:
>>
... snip ...
>>
Shouldn't it be unsigned char *? Anyway, my argument was that if
your compiler can perform arithmetic with the void *, then go
void *, as you did above.

Because a compiler can't 'perform arithmetic with the void*'. It
says so, right in the C standard. Trying to do so results in
undefined behaviour.
Because it's a constraint violation, it also requires the implementation to
issue a diagnostic message. See 3.3.6 of C89 or 6.5.6 of C99.

--
Richard Heathfield <http://www.cpax.org.uk>
Email: -http://www. +rjh@
Google users: <http://www.cpax.org.uk/prg/writings/googly.php>
"Usenet is a strange place" - dmr 29 July 1999
Sep 18 '08 #133
Nick Keighley wrote:
Richard<rgr...@gmail.comwrote:
.... snip ...
>
>My pointers were numbers. I could see them in the debugger.

but in general they aren't. Think DOS. Think IBM mainframe.
Are you trying to be dense?
No, he is just re-demonstrating the condition. I have seen many
explanations to him of this elementary fact.

--
[mail]: Chuck F (cbfalconer at maineline dot net)
[page]: <http://cbfalconer.home.att.net>
Try the download section.
Sep 18 '08 #134
On Sep 17, 5:57*pm, Keith Thompson <ks***@mib.orgwrote:
s0****@gmail.com writes:
>On Sep 17, 2:24*pm, Eric Sosman <Er*********@sun.comwrote:
[...]
>>* * *1) The function deals with the bytes that represent an object,
* * * * not with the object as such. *I/O functions, memcpy(),
* * * * free(), and so on are type-blind in this sense: They just
* * * * care about the object's bytes, not about its nature.
>Exactly, that's the "bytes" I was referring to. The word "bytes" is
also used to refer to characters. But I was referring to the bytes
that constitute an arbitrary object: int, double, struct, etc., and
that if examined, they will appear to have meaningless values. This is
also why I find it more natural to use void *: you aren't going to
examine what it points to, because all you're going to see are some
arbitrary bits that constitute an object of (possibly) bigger size.

unsigned char is used for both kinds of "bytes".
Sure, because it's the standard way. But I think you can now see why I
find void * more natural for the above kinds of "bytes."

Sebastian

Sep 18 '08 #135
s0****@gmail.com writes:
On Sep 17, 5:57*pm, Keith Thompson <ks***@mib.orgwrote:
>s0****@gmail.com writes:
>>On Sep 17, 2:24*pm, Eric Sosman <Er*********@sun.comwrote:
[...]
>>>* * *1) The function deals with the bytes that represent an object,
* * * * not with the object as such. *I/O functions, memcpy(),
* * * * free(), and so on are type-blind in this sense: They just
* * * * care about the object's bytes, not about its nature.
>>Exactly, that's the "bytes" I was referring to. The word "bytes" is
also used to refer to characters. But I was referring to the bytes
that constitute an arbitrary object: int, double, struct, etc., and
that if examined, they will appear to have meaningless values. This is
also why I find it more natural to use void *: you aren't going to
examine what it points to, because all you're going to see are some
arbitrary bits that constitute an object of (possibly) bigger size.

unsigned char is used for both kinds of "bytes".

Sure, because it's the standard way. But I think you can now see why I
find void * more natural for the above kinds of "bytes."
No, I really can't.

If I had the opportunity to go back in time and change C, I'd probably
separate the concepts of "byte" (the fundamental unit of storage) and
"character". I'd probably make "byte" a keyword and a type name,
referring to a numeric type similar to what we know as unsigned char,
and I'd allow sizeof(char) to be something other than 1. Given such a
change, it would make sense to access raw memory using type byte*, and
you could sensibly perform pointer arithmetic on such a type. I'm not
certain whether void*, a type that points to raw memory but that can't
can't be dereferenced or incremented, would add sufficient value to be
worth having in the language; perhaps memcpy and friends would just
take arguments of type byte*.

But it's *way* too late to make such a change in any language calling
itself "C".

If you want to a raw pointer that can point to any arbitrary object,
use void*. If you want to access the object's representation as bytes
or perform pointer arithmetic, use unsigned char*. If you want to
point to a specific type, or to an array of a specific type, use a
pointer to that type.

You cannot legally perform pointer arithmetic on void* in standard C,
and if you attempt to do so your code will be *gratuitously*
non-portable.

--
Keith Thompson (The_Other_Keith) ks***@mib.org <http://www.ghoti.net/~kst>
Nokia
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
Sep 18 '08 #136
Richard wrote:
Chris Dollin <ch**********@hp.comwrites:
>No, I am not saying that. I'm perfectly happy to believe that your
debugger renders bits of pointer as numbers.

Thats nice. How does your debugger do it?
Probably as numbers. How would I know? It's been so long*.
When you look into memory and you see your pointer stored in an
arry how does it look? Hex number by any chance? What a surprise.
If you cast it to a char * and subtract p
from ++p do you get 4 on a 32 bit machine? I did.....
I've never looked [at this using a debugger]. I've never needed to.
I understand C's computational model for pointers, and I understand
code generation, and I understand how a /particular/ implementation
can represent pointers in the same way it represents numbers, and I
don't confuse this with a /necessary/ property of implementations,
nor do I confuse scalars and vectors -- a segmented architectures
pointers are multi-component, like vectors, and just because you
can read off a bit-pattern and apply the traditional (but inappropriate)
binary decoding and get a number doesn't mean that bit-pattern
/is/ a number.

--
'It changed the future .. and it changed us.' /Babylon 5/

Hewlett-Packard Limited registered office: Cain Road, Bracknell,
registered no: 690597 England Berks RG12 1HN

Sep 18 '08 #137
Richard wrote:
The correct statement is

"It is incorrect to increment a non initialised variable since the
behaviour is undefined - however the value may well increment as
expected".
"Or not, at the whim of the implementor. DO NOT RELY ON THIS (if
you expect your code to be even vaguely portable)."

--
'It changed the future .. and it changed us.' /Babylon 5/

Hewlett-Packard Limited registered office: Cain Road, Bracknell,
registered no: 690597 England Berks RG12 1HN

Sep 18 '08 #138
On 17 Sep, 15:55, s0s...@gmail.com wrote:
On Sep 17, 3:02*am,Nick Keighley<nick_keighley_nos...@hotmail.com>
wrote:
On 16 Sep, 21:14, s0s...@gmail.com wrote:
>>>You have two options, do it portably, or do it with an extension, with
>>>absolutely no loss in efficiency or size, and you advice to choose the
>>>extension.
>>Well, perhaps the OP doesn't need portability (or at least not this
>>kind of portability).
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?

Because sometimes you don't need portability and because sometimes
there's a better way?
at the risk of repeating myself. I REALLY do not understand
how anyone can think like this. You wish to do something in C.
You have two options *that produce identical results* and are similar
in programming complexity. One is portable and one is not.

Why not use the portable version?
What is the <expletivepoint of using the non-portable version?
What can you possibly gain?

I'll probably give up after this. The trouble with text based
formats is you can't hear how hard I'm hitting my keyboard by
now.

>>Besides, void * seems more natural for this kind
>>of task.
rubbish

Why is it rubbish?
doing arithmatic on a void pointer seems really strange to me.
If you have a void pointer, it will typically point
to any kind of object: int, double, long long, structures, anything.
yup

Does it seem natural to you to treat such an object as if it were a
*character*?
no. It's not a character!

>* * *"This kind of task" was an artificial bit of code specifically
>written to experiment with manipulating pointers. *An investigative
>doodle, nothing more.
No. This "investigate doodle" demonstrated this kind of task. But this
kind of task is also common in real-world programs, and it's
important. I, for one, have actually done this, without realizing I
was using an extension.
so now you know- so don't do it again

Why not? I'll simply keep in mind that it works only under a certain
compiler.
<nick's head explodes>

--
Nick Keighley

Consistency is the last refuge of the unimaginative.
-- Oscar Wilde
Sep 18 '08 #139
Richard<rg****@gmail.comwrote:
Chris Dollin <ch**********@hp.comwrites:
No, I am not saying that. I'm perfectly happy to believe that your
debugger renders bits of pointer as numbers.

Thats nice. How does your debugger do it? When you look into memory and
you see your pointer stored in an arry how does it look? Hex number by
any chance? What a surprise.
My dear dunce, if you explicitly ask your debugger to hexdump
everything, _your DNA_ is a hex number. No surprise there, then.
OTOH, if I ask my debugger to do a stringdump of memory, all floating
point numbers will display as strings. Now, is a float therefore a
string?

Richard
Sep 18 '08 #140
s0****@gmail.com wrote:
On Sep 17, 5:57 pm, Keith Thompson <ks***@mib.orgwrote:
>s0****@gmail.com writes:
....
>>Exactly, that's the "bytes" I was referring to. The word "bytes" is
also used to refer to characters. But I was referring to the bytes
that constitute an arbitrary object: int, double, struct, etc., and
that if examined, they will appear to have meaningless values. This is
also why I find it more natural to use void *: you aren't going to
examine what it points to, because all you're going to see are some
arbitrary bits that constitute an object of (possibly) bigger size.
unsigned char is used for both kinds of "bytes".

Sure, because it's the standard way. But I think you can now see why I
find void * more natural for the above kinds of "bytes."
No, I do not see why you consider a type whose definition is that it
points at no specific type, to be the natural way of treating an object
as being composed of a series of bytes.

Fundamentally, the meaning of p+3, when p is a non-null pointer to an
object type, is that *(p+3) refers to an object of the pointed-at type
which is three objects of that type forward from the object referred to
by *p. That meaning disappears when *p itself is meaningless, which is
why the standard forbids pointer arithmetic on void* pointers.

The fact that some compilers provide void* arithmetic as an unnatural
extension to C doesn't make it natural. It just means that the users and
implementors of that feature don't properly understand what void* and
pointer arithmetic mean.
Sep 18 '08 #141
CBFalconer wrote:
s0****@gmail.com wrote:
... snip ...
>Shouldn't it be unsigned char *? Anyway, my argument was that if
your compiler can perform arithmetic with the void *, then go
void *, as you did above.

Because a compiler can't 'perform arithmetic with the void*'. It
says so, right in the C standard. Trying to do so results in
undefined behaviour.
So? How does that stop a compiler from doing so? Undefined behavior
includes, among it's infinite possibilities, permission to treat a void*
pointer as if it had been converted to char*.

The question is not whether a compiler can do so; many compilers do in
fact do so. If they issue a diagnostic message, they can even be fully
conforming compilers.

The real question is, given a fully conforming compiler which allows
such code as an extension, should a programmer take advantage of that
extension? I see no advantage to doing so, and lots of disadvantages,
Sebastion sees it the other way around, for reasons that make no sense
to me. But that's the real debate.
Sep 18 '08 #142
rl*@hoekstra-uitgeverij.nl (Richard Bos) writes:
Richard<rg****@gmail.comwrote:
>Chris Dollin <ch**********@hp.comwrites:
No, I am not saying that. I'm perfectly happy to believe that your
debugger renders bits of pointer as numbers.

Thats nice. How does your debugger do it? When you look into memory and
you see your pointer stored in an arry how does it look? Hex number by
any chance? What a surprise.

My dear dunce, if you explicitly ask your debugger to hexdump
everything, _your DNA_ is a hex number. No surprise there, then.
OTOH, if I ask my debugger to do a stringdump of memory, all floating
point numbers will display as strings. Now, is a float therefore a
string?
To be fair, a typical debugger probably displays pointers in hex or
something similar by default -- though on a segmented memory system
it's likely to use something like "1234:5678".

For example, gdb displays pointers in hex -- though not in a way that
supports Richard NoLastName's point. Here's a gdb session I just ran:

% gdb c
GNU gdb 6.8-debian
[...]
(gdb) break 6
Breakpoint 1 at 0x8048392: file c.c, line 6.
(gdb) run
Starting program: /home/kst/c

Breakpoint 1, main () at c.c:6
6 printf("x = %d, ptr = %p\n", x, (void*)ptr);
(gdb) list
1 #include <stdio.h>
2 int main(void)
3 {
4 int x = 42;
5 int *ptr = &x;
6 printf("x = %d, ptr = %p\n", x, (void*)ptr);
7 return 0;
8 }
(gdb) print x
$1 = 42
(gdb) print ptr
$2 = (int *) 0xbfa907a0
(gdb) continue
Continuing.
x = 42, ptr = 0xbfa907a0

Program exited normally.
(gdb) quit

Take a look at how it displayed the value of ptr, a variable of type
int*: "(int *) 0xbfa907a0". The authors of gdb know that pointers
aren't really integers, so gdb doesn't display them as integers; it
displays them using a valid C expression.

--
Keith Thompson (The_Other_Keith) ks***@mib.org <http://www.ghoti.net/~kst>
Nokia
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
Sep 18 '08 #143
On Sep 17, 8:24*pm, Eric Sosman <Eric.Sos...@sun.comwrote:
* * *2) The function is a framework operating on "abstracted data
* * * * types." *It doesn't know what kind of data it's handling,
* * * * but it passes the data pointers along to type-specific
* * * * functions that do know. *qsort() and bsearch() are examples
* * * * of this style.
Yeah, that is what I was thinking of ... qsort(). Seems that it is a
standard function. Is it normally implemented efficiently?

Anyway, here is my attempt at insertsort.

size = sizeof <data type>

I guess swap doesn't strictly need to be passed.

void insertsort( void *start, void *end, int size, int (*compare)(void
*, void *), void (*swap)(void *, void *) )
{

void *curpos = start;
void *swappos;

while( (char *)curpos <= (char *)end )
{
swappos = curpos;
while( (char *)swappos (char *)start && (*compare)( swappos ,
((char *)swappos - size) ) < 0 )
{
(*swap)( swappos , (void *)((char *)swappos - size) );
swappos = (char *)swappos - size;
}
curpos = (char *)curpos + size;
}

}
Sep 18 '08 #144
ra*****@gmail.com wrote:
[...]
Yeah, that is what I was thinking of ... qsort(). Seems that it is a
standard function. Is it normally implemented efficiently?
Yes. No. Maybe, maybe not. And that's my final answer. ;-)

As with most things, the definition of C just describes what qsort()
must do, not how it goes about doing it. That's to allow brilliant
implementors who invent nifty new sorting methods to take advantage of
their methods' superiority rather than be tied down to an inferior
algorithm specified by a Standard. (It also allows lazy implementors
the freedom to just transliterate something they found in Knuth or
Sedgewick without thinking too hard about it, so you never can tell ...)

There's an interesting paper by Jon Bentley and Doug McIlroy
titled "Engineering a Sort Function" that describes some real-life
problems discovered with real-life qsort() implementations, and how
they were addressed. I have no idea whether the implementors of
"normal" qsort() versions have read it.
Anyway, here is my attempt at insertsort.

size = sizeof <data type>

I guess swap doesn't strictly need to be passed.

void insertsort( void *start, void *end, int size, int (*compare)(void
*, void *), void (*swap)(void *, void *) )
It'd probably be better if the third argument were a size_t instead
of an int. Also, a few const qualifiers would be a nice addition:
int (*compare)(const void *, const void *). MOST OF ALL, a few
comments about what the arguments are, what the compare function must
do, and so on would be MORE THAN WELCOME. Get in the habit of writing
"usage comments" for your functions; not only is it helpful when you
want to use the functions six months from now, but you'll find that
writing the comments before writing the function helps clarify your
thinking about what the function must do, especially in corner cases.
{

void *curpos = start;
void *swappos;
You could eliminate a lot of ugly casts by changing these
from void* to char*. You might also find it helpful to have a
couple local char* variables to hold the converted values of
start and end.
while( (char *)curpos <= (char *)end )
Three comments. First, the casts are unnecessary: You can't
subtract two void* values, but you can compare them. Second,
things will probably be easier if the end pointer is "exclusive,"
that is, if it points just *after* the final element than at
the start of that element. Third, the initialization, test, and
increment of curpos would probably be better combined into a
single for statement than scattered to three disparate places.
{
swappos = curpos;
while( (char *)swappos (char *)start && (*compare)( swappos ,
((char *)swappos - size) ) < 0 )
A similar comment on the casts in the comparison. And a
similar comment on preferring for to while, although in this case
my preference is less pronounced (the manipulations on swappos are
closer together, hence easier to comprehend). Also, you can just
write compare(...) instead of (*compare)(...) -- some people like
it one way, some the other, but just be aware that you have a choice.
{
(*swap)( swappos , (void *)((char *)swappos - size) );
The cast to void* isn't needed. Also, the same comment
about (*swap) as about (*compare) above.
swappos = (char *)swappos - size;
}
curpos = (char *)curpos + size;
}

}
--
Er*********@sun.com
Sep 18 '08 #145

"Jean-Marc Bourguet" <jm@bourguet.orgwrote in message
news:87************@news.bourguet.org...
Richard<rg****@gmail.comwrites:
For the fun, I've also this machine to which I telnetted to run a little
program. That may interest you:

@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[i]);
}
return 0;
}
@run pvoid
&x = 331100050105
&x = 50105
&y = 1100050106
&t[0] = 331100050107
&t[1] = 221100050107
&t[2] = 111100050107
&t[3] = 1100050107
&t[4] = 331100050110
&t[5] = 221100050110
&t[6] = 111100050110
&t[7] = 1100050110
&t[8] = 331100050111
&t[9] = 221100050111

pointers are printed as number here, but they probably don't behave like
you'd expect. BTW, a debugger would have printed the first and third as
331100,,50105 and 1100,,50106. To understand the void* one, you have to
know that those are byte pointers, pointing to bytes made of 9 bits (11
octal is 9 decimal, octal being the base commonly use on this 36 bits
machines) inside 36 bits words. Those starting by 33 are pointing to the
least significant 9 bit byte of the word (starting at bit 33 octal -- 27
in
decimal).

Admitly this is quite an older machine, but at a time it was the most
common architecture on the Arpanet. The one I telnetted to was an
emulated
one, but there are still some hardware one on the Internet. There is also
gcc 4.3 port for it, and I suspect the company which is paying to make
that
port still makes hardware implementation even if it doesn't sell them
outside systems.
You're not saying what machine this is?

I'm guessing pdp-10. But I'm not sure if those funny pointers are done in
software or if it's using the special bitfield instructions; these use
pointers with a standard 18-bit address in low half and extra bit
position/width in top half.
>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.

The world is more diverse that you think?
That machine is also obsolete. Byte-addressable machines were a breath of
fresh air. I just hope word-addressed machines don't make a big comeback.
>But they ARE still numbers. Like it or not. The interpretation depends on
your point of view.

You can consider any bit pattern as a number, but when it is an address
that is not always the best thing to do.
In this case treating addresses as /integers/ would not have worked (for
incrementing and so on), but no harm in considering the address as a kind of
number, similar to a float which also uses special fields within the 36-bit
word.

BTW what would address to int conversion have done in this case, just done
nothing, or linearised the address?

--
Bartc

Sep 19 '08 #146
In article <6b**********************************@m45g2000hsb. googlegroups.com>
<s0****@gmail.comwrote:
>That's an excellent point: what if you _don't_ know what it's really
pointing to? For example, functions such as memcpy(), memmove(),
memset(), etc., are used extensively to deal with objects of any type.
So this functions take void *'s, and they might be pointing to an int,
to a char, to a structure, or anything you can think of. I'm sure the
implementor of such a function would find it enjoyable to be able to
perform void pointer arithmetic!
As someone who has actually written a number of these implementation
functions, I can answer to the last statement here (about "find[ing]
it enjoyable"): no, it really makes essentially no difference.

Here is a classic example of a linear search function (which I am
typing in "on the fly", otherwise I would show a binary search
modeled after bsearch()). Note where "void *" appears and where
it does not.

/*
* Linear search: search "nmemb" items of size "size", starting
* at "base", for the given "key". Return a pointer to the
* item found, or NULL if the item is not found.
*
* Comparisons between keys and items are done by calling the
* compar() function, which should return 0 if they match,
* nonzero otherwise.
*/
void *lsearch(const void *key, const void *base0,
size_t nmemb, size_t size,
int (*compar)(const void *, const void *)) {
const unsigned char *base = base0;
size_t i;

for (i = 0; i < nmemb; i++, base += size)
if (compar(key, base) == 0)
return (void *)base; /* cast away const */
return NULL;
}

In GNUC, where sizeof(void)==1, I can replace "const void *base0"
with "const void *base" and remove the first line of the function.
Otherwise, the entire function remains exactly the same. (The cast
on the return value is still required, as lsearch() mimicks bsearch()
and de-consts its return value.) The code generated by any reasonably
good compiler also remains the same.

(Since linear search is slow, you probably want to call bsearch()
anyway. The bsearch() code is a bit more complex, so the "extra"
line, "const unsigned char *base = base0", adds even less to the
source, percentage-wise. As I said above, I would have shown a
bsearch(), but for two things: I might get it wrong, and the
name bsearch() is reserved to the implementation.)
--
In-Real-Life: Chris Torek, Wind River Systems
Salt Lake City, UT, USA (4039.22'N, 11150.29'W) +1 801 277 2603
email: gmail (figure it out) http://web.torek.net/torek/index.html
Sep 20 '08 #147
Peter Nilsson <ai***@acay.com.auwrote:
Keith Thompson <ks...@mib.orgwrote:
... why does printf have a "%p" format?

That's actually a very good question! If you ever hear
a good answer, please share it.
So you can print pointers (e.g., for debugging) in the native format for
the platform without having to know in advance what that is. (Yes,
there's no guarantee that %p actually does that, but only a very poor
quality implementation would do anything else.)
--
Larry Jones

Even if lives DID hang in the balance, it would depend on whose they were.
-- Calvin
Sep 26 '08 #148
Keith Thompson <ks***@mib.orgwrites:
CBFalconer <cb********@yahoo.comwrites:
[...]
In addition, as far as I can tell, there is no prohibition against
returning void* and char* pointers in different registers (or other
entities). If this is correct, using the interchangeably can
create an ugly code block.

There is no such prohibition in the normative text of the standard,
but it's suggested in a footnote.

C99 6.2.5p27:

A pointer to void shall have the same representation and alignment
requirements as a pointer to a character type.

And a footnote:

The same representation and alignment requirements are meant to
imply interchangeability as arguments to functions, return values
from functions, and members of unions.

This is an unfortunate flaw in the standard.
I think you're misunderstanding the idea behind the footnote.
The "interchangeability" of char*/void* is meant to talk about
values of those types used in particular contexts, not about
derived types with those types in them. For example,

char *
xyzzy(){
void *r = "answer";
return * (char**) &r;
}

is the sort of case the footnote means to address. This
interchangeability does not extend to derived types, such as
trying to convert &xyzzy to (void *(*)()). There's a similar
relationship between int and unsigned int; as values, int and
unsigned int are (often) interchangeable, but pointers to int and
pointers to unsigned int don't bear any special relationship to
each other -- they don't even have to be the same size, for
example. The analogy with function types that have int or
unsigned int in them should be clear.
Oct 9 '08 #149
Tim Rentsch <tx*@alumnus.caltech.eduwrites:
Keith Thompson <ks***@mib.orgwrites:
>CBFalconer <cb********@yahoo.comwrites:
[...]
In addition, as far as I can tell, there is no prohibition against
returning void* and char* pointers in different registers (or other
entities). If this is correct, using the interchangeably can
create an ugly code block.

There is no such prohibition in the normative text of the standard,
but it's suggested in a footnote.

C99 6.2.5p27:

A pointer to void shall have the same representation and alignment
requirements as a pointer to a character type.

And a footnote:

The same representation and alignment requirements are meant to
imply interchangeability as arguments to functions, return values
from functions, and members of unions.

This is an unfortunate flaw in the standard.

I think you're misunderstanding the idea behind the footnote.
The "interchangeability" of char*/void* is meant to talk about
values of those types used in particular contexts, not about
derived types with those types in them.
[snip]

Consider this:

printf("%p\n", "string literal");

I see nothing in the normative text of the standard that requires
char* and void* to be passed as function arguments in the same manner;
for example, void* arguments might be passed in one set of registers
and char* arguments in another. I can think of no good reason to do
so, but the standard doesn't forbid it. The footnote, however,
implies that the above must print (in some implementation-defined
manner) the address of the first character of the literal.

--
Keith Thompson (The_Other_Keith) ks***@mib.org <http://www.ghoti.net/~kst>
Nokia
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
Oct 9 '08 #150

This discussion thread is closed

Replies have been disabled for this discussion.

Similar topics

11 posts views Thread by kazack | last post: by
18 posts views Thread by steve | last post: by
14 posts views Thread by streamkid | last post: by
21 posts views Thread by Bo Yang | last post: by
4 posts views Thread by Jeffrey Spoon | last post: by
10 posts views Thread by Zero | last post: by
21 posts views Thread by Chad | last post: by
18 posts views Thread by mdh | last post: by
28 posts views Thread by junky_fellow | last post: by
1 post views Thread by CARIGAR | last post: by
reply views Thread by suresh191 | last post: by
reply views Thread by harlem98 | last post: by
reply views Thread by harlem98 | last post: by
By using this site, you agree to our Privacy Policy and Terms of Use.