Can I do arithmetic on void * pointers in C?

2019-01-19 11:41发布

is this valid

void *p = &X; /* some thing */
p += 12;

and if so what does p now point to? I have (third party) code that does this (and compiles cleanly) and my guess is that the void * was treated as a char *. My trusty K&R is silent(ish) on the topic

EDIT: My little test app runs fine on gcc 4.1.1 and treats void * as char *. But g++ barfs

I know how to do it properly. I need to know if I have to clean this code base to find all the places its done.

BTW gcc -pedantic throws up a warning

Summary:

The C spec is ambiguous. It says that in terms of representation and use as function parameters void* =char*. But it is silent regarding pointer arithmetic.

  • gcc (4) permits it and treats it as char *
  • g++ refuses it
  • gcc -pedantic warns about it
  • vs2010 both c and c++ refuses it

6条回答
贪生不怕死
2楼-- · 2019-01-19 11:47

You may want to have a look at the top voted answer for this question

Pointer arithmetic for void pointer in C

查看更多
你好瞎i
3楼-- · 2019-01-19 11:51

Your guess is correct.

In the standard ISO C99, section 6.2.5 paragraph 26, it declares that void pointers and character pointers will have the same representation and alignment requirements (paraphrasing).

查看更多
爷、活的狠高调
4楼-- · 2019-01-19 11:56

It depends on compiler. Those that allow it consider sizeof(*(void *)) as 1.

EDIT: it's only for void pointer arithmetic. It would have no sense using in this case steps of sizeof(int) or of 0. The common expectations of someone who uses it would be the smallest possible step.

查看更多
干净又极端
5楼-- · 2019-01-19 12:01

I don't think you can, because it doesn't know its type, therefore can not seek the correct amount of bytes.

Cast it to a type first, i.e. (int).

查看更多
萌系小妹纸
6楼-- · 2019-01-19 12:10

No this is not legal. A void* cannot be arbitrarily incremented. It needs to be cast to a specific type first.

If you want to increment it by a specific number of bytes then this is the solution I use.

p = ((char*)p) + 12;

The char type is convenient because it has a defined size of 1 byte.

EDIT

It's interesting that it runs on gcc with a warning. I tested on Visual Studio 2010 and verified it does not compile. My limited understanding of the standard would say that gcc in the error here. Can you add the following compilation flags

-Wall -ansi -pedantic
查看更多
The star\"
7楼-- · 2019-01-19 12:14

To quote from the spec:

§6.5.6/2: For addition, either both operands shall have arithmetic type, or one operand shall be a pointer to an object type and the other shall have integer type. (Incrementing is equivalent to adding 1.)

A pointer to void is not a pointer to an object type, as per these excerpts:

§6.2.5/1: [...] Types are partitioned into object types (types that fully describe objects), function types (types that describe functions), and incomplete types (types that describe objects but lack information needed to determine their sizes).

§6.2.5/19: The void type comprises an empty set of values; it is an incomplete type that cannot be completed.

Therefore, pointer arithmetic is not defined for pointer to void types.

查看更多
登录 后发表回答