incrementing void *

  • Thread starter subramanian100in
  • Start date
S

subramanian100in

I saw this question from www.brainbench.com

void *ptr;
myStruct myArray[10];

ptr = myArray;

Which of the following is the correct way to increment the variable
"ptr"?
Choice 1 ptr = ptr + sizeof(ptr);
Choice 2 increment(ptr);
Choice 3 ++(int*)ptr;
Choice 4 ptr = ptr + sizeof(myArray);
Choice 5 ptr = ptr + sizeof(myStruct);

THEIR Correct Answer given in this site is: ptr = ptr +
sizeof(myStruct);

But my answer is ++(int*)ptr. The reason is that ptr being void *, we
cannot add any number to it. It must be cast to a valid object before
incrementing.

Which is correct ?
 
I

Ian Collins

I saw this question from www.brainbench.com

void *ptr;
myStruct myArray[10];

ptr = myArray;

Which of the following is the correct way to increment the variable
"ptr"?
Choice 1 ptr = ptr + sizeof(ptr);
Choice 2 increment(ptr);
Choice 3 ++(int*)ptr;
Choice 4 ptr = ptr + sizeof(myArray);
Choice 5 ptr = ptr + sizeof(myStruct);

THEIR Correct Answer given in this site is: ptr = ptr +
sizeof(myStruct);

But my answer is ++(int*)ptr. The reason is that ptr being void *, we
cannot add any number to it. It must be cast to a valid object before
incrementing.
(int*)ptr isn't an lvalue, so you can not increment it.
Which is correct ?
ptr = ptr + sizeof(myStruct);
 
P

P.J. Plauger

I saw this question from www.brainbench.com

void *ptr;
myStruct myArray[10];

ptr = myArray;

Which of the following is the correct way to increment the variable
"ptr"?
Choice 1 ptr = ptr + sizeof(ptr);
Choice 2 increment(ptr);
Choice 3 ++(int*)ptr;
Choice 4 ptr = ptr + sizeof(myArray);
Choice 5 ptr = ptr + sizeof(myStruct);

THEIR Correct Answer given in this site is: ptr = ptr +
sizeof(myStruct);

But my answer is ++(int*)ptr. The reason is that ptr being void *, we
cannot add any number to it. It must be cast to a valid object before
incrementing.
(int*)ptr isn't an lvalue, so you can not increment it.

Nonsense. There are dangers in incrementing (int *)ptr if
myStruct is not on at least as strong a storage boundary as
int (or if you're on a machine where even ten MyStruct are
smaller than a single int). But lvaleness has nothing to do
with it.
ptr = ptr + sizeof(myStruct);

Nonsense. You can't add anything to a void *.

The posed question doesn't answer the burning question,
"increment by what?". One possible sensible interpretation
is to undo the implicit void cast and write:

ptr = ++((myStruct *)ptr);

Yet another is:

ptr = ++((myStruct[10] *)ptr);

These at least have the virtue of being well defined. But
then so does:

ptr = ++(char *)ptr);

so the problem is at least ambiguous. And we still don't
know what the function increment does.

I predict a very long, unimportant thread.

P.J. Plauger
Dinkumware, Ltd.
http://www.dinkumware.com
 
S

subramanian100in

I myself know that ++(int *)ptr is not correct. But among the five
choices given and if one choice has to be selected,
only ++(int *)ptr can be incremented because only in this case, object
size is known for doing the incrementation.
 
I

Ian Collins

P.J. Plauger said:
Nonsense. There are dangers in incrementing (int *)ptr if
myStruct is not on at least as strong a storage boundary as
int (or if you're on a machine where even ten MyStruct are
smaller than a single int). But lvaleness has nothing to do
with it.
Oops, I appear to have posted complete bollocks. Sorry.
 
S

santosh

I saw this question from www.brainbench.com

void *ptr;
myStruct myArray[10];

ptr = myArray;

Which of the following is the correct way to increment the variable
"ptr"?
Choice 1 ptr = ptr + sizeof(ptr);
Choice 2 increment(ptr);
Choice 3 ++(int*)ptr;
Choice 4 ptr = ptr + sizeof(myArray);
Choice 5 ptr = ptr + sizeof(myStruct);

None. The closest is choice two, depending on what the function
exactly does.
THEIR Correct Answer given in this site is: ptr = ptr +
sizeof(myStruct);

You cannot do any arithmetic on void pointers.
But my answer is ++(int*)ptr. The reason is that ptr being void *, we
cannot add any number to it. It must be cast to a valid object before
incrementing.

But why a cast to int *? The more likely cast would be to myStruct *
or myStruct[10] *. Also you can use a cast to unsigned char * to
access the bytes of the array myArray.
 
S

santosh

I myself know that ++(int *)ptr is not correct.

It's not that it is not correct. It's just likely to be wrong.
But among the five
choices given and if one choice has to be selected,
only ++(int *)ptr can be incremented because only in this case, object
size is known for doing the incrementation.

It would work only if myStruct's alignment requirements are only as
strict as for an int, something that's unlikely unless myStruct
happens to be an obfuscatory typedef for int.

I myself, if forced, would've chosen choice two.
 
S

santosh

P.J. Plauger said:
I saw this question from www.brainbench.com

void *ptr;
myStruct myArray[10];

ptr = myArray;

Which of the following is the correct way to increment the variable
"ptr"?
Choice 1 ptr = ptr + sizeof(ptr);
Choice 2 increment(ptr);
Choice 3 ++(int*)ptr;
Choice 4 ptr = ptr + sizeof(myArray);
Choice 5 ptr = ptr + sizeof(myStruct);

THEIR Correct Answer given in this site is: ptr = ptr +
sizeof(myStruct);

But my answer is ++(int*)ptr. The reason is that ptr being void *, we
cannot add any number to it. It must be cast to a valid object before
incrementing.

[ ... ]
Nonsense. You can't add anything to a void *.

The posed question doesn't answer the burning question,
"increment by what?". One possible sensible interpretation
is to undo the implicit void cast and write:

ptr = ++((myStruct *)ptr);

Shouldn't this be:

ptr = ((myStruct *) ptr) + 1;

and similarly for the others?
 
K

Keith Thompson

P.J. Plauger said:
Ian Collins said:
I saw this question from www.brainbench.com

void *ptr;
myStruct myArray[10];

ptr = myArray;

Which of the following is the correct way to increment the variable
"ptr"?
Choice 1 ptr = ptr + sizeof(ptr);
Choice 2 increment(ptr);
Choice 3 ++(int*)ptr;
Choice 4 ptr = ptr + sizeof(myArray);
Choice 5 ptr = ptr + sizeof(myStruct);

THEIR Correct Answer given in this site is: ptr = ptr +
sizeof(myStruct);

But my answer is ++(int*)ptr. The reason is that ptr being void *, we
cannot add any number to it. It must be cast to a valid object before
incrementing.
(int*)ptr isn't an lvalue, so you can not increment it.

Nonsense. There are dangers in incrementing (int *)ptr if
myStruct is not on at least as strong a storage boundary as
int (or if you're on a machine where even ten MyStruct are
smaller than a single int). But lvaleness has nothing to do
with it.

Um, are you sure you're not thinking of the C++ rules?

The result of a cast is not an lvalue, and the argument to "++" must
be an lvalue, so Choice 3 is a constraint violation. (Both gcc and
Sun's C compiler complain about it; that doesn't prove anything, but
it does bolster my confidence.) You can add 1 to it, but you can't
increment it with "++".

(Choices 1, 4, and 5 are also constraint violations, since addition
isn't defined for void*. Choice 2 *could* be correct if "increment"
were a carefully crafted macro, but I don't think that's the intent.)
ptr = ptr + sizeof(myStruct);

Nonsense. You can't add anything to a void *.

The posed question doesn't answer the burning question,
"increment by what?". One possible sensible interpretation
is to undo the implicit void cast and write:

ptr = ++((myStruct *)ptr);

Yet another is:

ptr = ++((myStruct[10] *)ptr);

These at least have the virtue of being well defined. But
then so does:

ptr = ++(char *)ptr);

so the problem is at least ambiguous. And we still don't
know what the function increment does.

All three of these, if a cast yielded an lvalue, would modify ptr
twice between sequence points and therefore invoke undefined behavior
(<PICKY>and the last one has a missing parenthesis</PICKY>). Changing
"++" to "1 + " should fix that.

I understand that *some* casts in C++ yield lvalues, but I don't know
the rules. Perhaps the question on brainbench.com was actually about
C++? Or maybe it was just wrong.

I'm hesitant to take the risk of disagreeing with P.J. Plauger, but
either I'm right or I'm about to learn something.
 
K

Keith Thompson

santosh said:
I saw this question from www.brainbench.com

void *ptr;
myStruct myArray[10];

ptr = myArray;

Which of the following is the correct way to increment the variable
"ptr"?
Choice 1 ptr = ptr + sizeof(ptr);
Choice 2 increment(ptr);
Choice 3 ++(int*)ptr;
Choice 4 ptr = ptr + sizeof(myArray);
Choice 5 ptr = ptr + sizeof(myStruct);

None. The closest is choice two, depending on what the function
exactly does.
[...]

If increment is a function, it can't modify ptr. It could be a macro,
though.
 
S

Servé Laurijssen

Keith Thompson said:
Um, are you sure you're not thinking of the C++ rules?

The result of a cast is not an lvalue, and the argument to "++" must
be an lvalue, so Choice 3 is a constraint violation. (Both gcc and
Sun's C compiler complain about it; that doesn't prove anything, but
it does bolster my confidence.) You can add 1 to it, but you can't
increment it with "++".

it doesnt work in C++ either. +1 would be best
 
R

Richard Tobin

(int*)ptr isn't an lvalue, so you can not increment it.
[/QUOTE]
Nonsense. There are dangers in incrementing (int *)ptr if
myStruct is not on at least as strong a storage boundary as
int (or if you're on a machine where even ten MyStruct are
smaller than a single int). But lvaleness has nothing to do
with it.

You can add 1 to (int *)ptr, but you can't assign the result to
it, because (int *)ptr is indeed not an lvalue (since some draft
of C89).

You can do ptr = (int *)ptr + 1 which converts the value back
to void * before assigning it to plain uncast ptr.

-- Richard
The posed question doesn't answer the burning question,
"increment by what?". One possible sensible interpretation
is to undo the implicit void cast and write:

ptr = ++((myStruct *)ptr);

I think you're temporarily confused. You can't apply ++ to cast
expressions in standard C.

-- Richard
 
R

Richard Tobin

Keith Thompson said:
The result of a cast is not an lvalue, and the argument to "++" must
be an lvalue, so Choice 3 is a constraint violation. (Both gcc and
Sun's C compiler complain about it; that doesn't prove anything, but
it does bolster my confidence.)

gcc has traditionally allowed this as an extension; gcc 4.0 reports

warning: target of assignment not really an lvalue; this will be a
hard error in the future

-- Richard
 
S

santosh

Keith said:
santosh said:
I saw this question from www.brainbench.com

void *ptr;
myStruct myArray[10];

ptr = myArray;

Which of the following is the correct way to increment the variable
"ptr"?
Choice 1 ptr = ptr + sizeof(ptr);
Choice 2 increment(ptr);
Choice 3 ++(int*)ptr;
Choice 4 ptr = ptr + sizeof(myArray);
Choice 5 ptr = ptr + sizeof(myStruct);

None. The closest is choice two, depending on what the function
exactly does.
[...]

If increment is a function, it can't modify ptr. It could be a macro,
though.

Yes, careless of me. It's unlikely to be a macro though, given that
it's in lower case.
 
A

ais523

Keith said:
santosh said:
(e-mail address removed), India wrote:
I saw this question fromwww.brainbench.com
void *ptr;
myStruct myArray[10];
ptr = myArray;
Which of the following is the correct way to increment the variable
"ptr"?
Choice 1 ptr = ptr + sizeof(ptr);
Choice 2 increment(ptr);
Choice 3 ++(int*)ptr;
Choice 4 ptr = ptr + sizeof(myArray);
Choice 5 ptr = ptr + sizeof(myStruct);
None. The closest is choice two, depending on what the function
exactly does. [...]

If increment is a function, it can't modify ptr. It could be a macro,
though.

Yes, careless of me. It's unlikely to be a macro though, given that
it's in lower case
There are several lowercase macros in the standard; stdin (as long as
<stdio.h> is #included) is one I can think of off the top of my head,
and I know there are others. Anyway, the problem here is that the
answer to 'what is the correct way to increment a void* variable' is
'you don't increment void* variables'; incrementing a void* variable
can't sensibly be defined because void is an incomplete type. The
(incorrect, because sizeof(void) can't be taken) "ptr = (char*)ptr +
sizeof(void);" would come nearest to what the question is asking. On
the other hand, the answer to "what is the correct way to cause ptr to
point at the element of myArray after the one it's currently pointing
at" would be ptr=1+(myStruct*)ptr, assuming that myStruct is a typedef
for a user-defined struct type (which would seem plausible from the
name, but this hasn't been stated). Out of the choices actually given,
2 is the only one that stands a chance of being correct (if increment
is a carefully-defined macro); 1, 4, and 5 all try to do arithmetic on
void* (impossible because void is incomplete), and 3 isn't legal in C
(but is an extension I've seen on more than one compiler, and which I
would use in some cases if it were portable, obviously using myStruct*
rather than int*).
 
E

Eric Sosman

I saw this question from www.brainbench.com

void *ptr;
myStruct myArray[10];

ptr = myArray;

Which of the following is the correct way to increment the variable
"ptr"?
Choice 1 ptr = ptr + sizeof(ptr);
Choice 2 increment(ptr);
Choice 3 ++(int*)ptr;
Choice 4 ptr = ptr + sizeof(myArray);
Choice 5 ptr = ptr + sizeof(myStruct);

THEIR Correct Answer given in this site is: ptr = ptr +
sizeof(myStruct);

But my answer is ++(int*)ptr. The reason is that ptr being void *, we
cannot add any number to it. It must be cast to a valid object before
incrementing.

Which is correct ?

Unless I'm very much mistaken, all five are wrong.

1) Pointer arithmetic is not defined for pointers
to incomplete types. (6.5.6/2)

2) The C language has no keyword, built-in function,
or macro named `increment'.

3) The `++' operator requires a modifiable lvalue as
its operand, and `(int*)ptr' is not a modifiable
lvalue. (6.5.3.1/1, 6.3.2.1/1)

4) See 1.

5) See 1.

A possible quibble could be advanced in favor of 2.
One could make the answer correct (for some definition of
"correct") by introducing an `increment' macro that would
in some sense "increment" its operand. That's trick
question territory, though, and beneath contempt.
 
A

AdrianH

I saw this question fromwww.brainbench.com

void *ptr;
myStruct myArray[10];

ptr = myArray;

Which of the following is the correct way to increment the variable
"ptr"?
Choice 1 ptr = ptr + sizeof(ptr);
Choice 2 increment(ptr);
Choice 3 ++(int*)ptr;
Choice 4 ptr = ptr + sizeof(myArray);
Choice 5 ptr = ptr + sizeof(myStruct);

THEIR Correct Answer given in this site is: ptr = ptr +
sizeof(myStruct);

Who is 'THEIR'?
But my answer is ++(int*)ptr. The reason is that ptr being void *, we
cannot add any number to it. It must be cast to a valid object before
incrementing.

Which is correct ?

I would say "none of the above... maybe".
Choice 1 ptr = ptr + sizeof(ptr);

No, ptr is a void * and void has no size, thus it cannot move the
pointer and is considered an error.
Choice 2 increment(ptr);

This cannot work in C, there is no way of passing ptr by reference
unless you do so explicitly with the & operator.
Choice 3 ++(int*)ptr;

This is the maybe as this may or may not produce an lvalue given
certain compilers. It is not recommended.
Choice 4 ptr = ptr + sizeof(myArray);

Same answer as Choice 1.
Choice 5 ptr = ptr + sizeof(myStruct);

Same answer as Choice 1.

That said, choice 2 and 3 are close, and could work if tweaked:

Choice 2
increment(ptr); // wrong, passing by value cannot change
ptr's value
increment(&ptr); // could work if increment takes a ** and
wraps what actually happens.
Choice 3
++(int*)ptr;
++*(int**)&ptr;

That said, my mod to choice 3 may not work either under some systems
as I think that I read somewhere that conversion of a pointer may not
work as there are special pointers to certain types. I.e. a int
pointer may not be the same as a double pointer. Unfortunately, I
don't remember the reference but should still work in most cases.

The safest bet is doing this:

int * intPtr = (int*)ptr;
++intPtr;
ptr = (void*)intPtr;

Which in my mind would be what is happening internally if you did +
+*(int**)&ptr; If increment is wrapped in a macro which does this,
than it would work. A more generalised macro would be:

#define increment(fromType, toType, ptr) do { \
toType * _tmpPtr_ = (toType*)ptr; \
++_tmpPtr_; \
ptr = (fromType*)_tmpPtr_; \
} while (0)

and then do this:

increment(void, int, ptr);

An increment function that assumes to increment a void pointer as if
it were an int would be:
void increment(void** prt)
{
int* intPtr = (int*)*prt;
++intPtr;
*ptr = (void*)intPtr;
}

but a more generalised solution would be this:

void increment(void** ptr, size_t size)
{
char* charPtr = (char*)*prt;
charPtr += size;
*ptr = (void*)charPtr;
}

the first would be used like:

increment(&ptr);

the second would be used like:

increment(&ptr, sizeof(int));

Does this make sense to you?


Adrian
 
A

Adrian Hawryluk

AdrianH said:
On Mar 9, 12:43 am, "(e-mail address removed), India"
Choice 3
++(int*)ptr;

I've also seen people use this trick, though how portable it is I'm not
sure due to the possiblity that a pointer to different types may not
necessarily be the same (in size or otherwise).

typedef union {
void * vp;
int * ip;
} p;

p ptr = <whatever>; // assigned to void *
++p.ip;


Adrian
 
R

Richard Heathfield

Adrian Hawryluk said:
I've also seen people use this trick, though how portable it is I'm
not sure due to the possiblity that a pointer to different types may
not necessarily be the same (in size or otherwise).

typedef union {
void * vp;
int * ip;
} p;

p ptr = <whatever>; // assigned to void *
++p.ip;

This will indeed fail on implementations where the representations of
void * and int * differ. For example, to quote the FAQ: "Some 64-bit
Cray machines represent int * in the lower 48 bits of a word; char *
additionally uses some of the upper 16 bits to indicate a byte address
within a word."
 
S

spacecriter \(Bill C\)

I saw this question from www.brainbench.com

void *ptr;
myStruct myArray[10];

ptr = myArray;

Which of the following is the correct way to increment the variable
"ptr"?
Choice 1 ptr = ptr + sizeof(ptr);
Choice 2 increment(ptr);
Choice 3 ++(int*)ptr;
Choice 4 ptr = ptr + sizeof(myArray);
Choice 5 ptr = ptr + sizeof(myStruct);

THEIR Correct Answer given in this site is: ptr = ptr +
sizeof(myStruct);

But my answer is ++(int*)ptr. The reason is that ptr being void *, we
cannot add any number to it. It must be cast to a valid object before
incrementing.

Which is correct ?

How about something along the lines of:

ptr = &myArray[j++];
 

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

Forum statistics

Threads
473,773
Messages
2,569,594
Members
45,122
Latest member
VinayKumarNevatia_
Top