Question about void pointers

K

Keith Thompson

Richard said:
Chris Dollin said:
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
<[email protected]>, available at
<http://groups.google.com/group/comp.lang.c/msg/d4dc17f7d5a2e317>,
you wrote:

| (e-mail address removed) writes:
| > On Sep 16, 7:13 pm, (e-mail address removed) 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.
 
K

Keith Thompson

CBFalconer said:
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.
 
S

s0suk3

On Sep 17, 10:22 am, (e-mail address removed) wrote:
On Sep 17, 5:55 pm, (e-mail address removed) 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.
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.
Give me a good argument not to.

Because it's crap. See previous posts to learn why.
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
 
J

James Kuyper

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

s0suk3

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
 
J

James Kuyper

Richard said:
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.
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.
I dont recall ever saying that.

Follow up the two citations in my other message.
 
K

Keith Thompson

On Sep 17, 3:02 am, Nick Keighley <[email protected]>
wrote:
On 16 Sep, 21:14, (e-mail address removed) 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*.
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.
 
J

James Kuyper

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

Kenny McCormack

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

s0suk3

(e-mail address removed) writes:


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
 
J

James Kuyper

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

Keith Thompson

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?
 
S

s0suk3

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
 
S

s0suk3

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
 
J

jameskuyper

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*.
 
J

jameskuyper

(e-mail address removed) 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.
 
S

s0suk3

     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
 
K

Keith Thompson

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

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,770
Messages
2,569,583
Members
45,073
Latest member
DarinCeden

Latest Threads

Top