简体   繁体   English

我可以对C中的void *指针进行算术运算吗?

[英]Can I do arithmetic on void * pointers in C?

is this valid 这是有效的

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

and if so what does p now point to? 如果是的话,p现在指向什么? I have (third party) code that does this (and compiles cleanly) and my guess is that the void * was treated as a char *. 我有(第三方)代码执行此操作(并编译干净)我的猜测是void *被视为char *。 My trusty K&R is silent(ish) on the topic 我信赖的K&R对此话题保持沉默(ish)

EDIT: My little test app runs fine on gcc 4.1.1 and treats void * as char *. 编辑:我的小测试应用程序在gcc 4.1.1上正常运行并将void *视为char *。 But g++ barfs 但是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 BTW gcc -pedantic发出警告

Summary: 摘要:

The C spec is ambiguous. C规范含糊不清。 It says that in terms of representation and use as function parameters void* =char*. 它表示在表示和用作函数参数方面void * = char *。 But it is silent regarding pointer arithmetic. 但它对指针算法没有提及。

  • gcc (4) permits it and treats it as char * gcc(4)允许它并将其视为char *
  • g++ refuses it g ++拒绝它
  • gcc -pedantic warns about it gcc -pedantic警告它
  • vs2010 both c and c++ refuses it vs2010 c和c ++都拒绝它

No this is not legal. 不,这不合法。 A void* cannot be arbitrarily incremented. void*不能任意增加。 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. char类型很方便,因为它的定义大小为1个字节。

EDIT 编辑

It's interesting that it runs on gcc with a warning. 有趣的是它在gcc上运行并发出警告。 I tested on Visual Studio 2010 and verified it does not compile. 我在Visual Studio 2010上测试并验证它不能编译。 My limited understanding of the standard would say that gcc in the error here. 我对标准的理解有限,会说gcc出现错误。 Can you add the following compilation flags 可以添加以下编译标志吗?

-Wall -ansi -pedantic

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. §6.5.6/ 2 :对于加法,两个操作数都应具有算术类型,或者一个操作数应是指向对象类型的指针,另一个操作数应具有整数类型。 (Incrementing is equivalent to adding 1.) (递增相当于添加1.)

A pointer to void is not a pointer to an object type, as per these excerpts: 指向void的指针不是指向对象类型的指针,根据以下摘录:

§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/ 1 :[...]类型被划分为对象类型(完全描述对象的类型),函数类型(描述函数的类型)和不完整类型(描述对象但缺少确定其所需信息的类型)大小)。

§6.2.5/19 : The void type comprises an empty set of values; §6.2.5/ 19 :void类型包含一组空值; it is an incomplete type that cannot be completed. 它是一种不完整的类型,无法完成。

Therefore, pointer arithmetic is not defined for pointer to void types. 因此, 没有为指向void类型的指针定义指针算术。

It depends on compiler. 这取决于编译器。 Those that allow it consider sizeof(*(void *)) as 1. 那些允许它将sizeof(*(void *))视为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. 在这种情况下使用sizeof(int)或0的步骤是没有意义的。使用它的人的共同期望是可能的最小步骤。

You may want to have a look at the top voted answer for this question 您可能想要查看此问题的最高投票答案

Pointer arithmetic for void pointer in C C中空指针的指针算法

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). 在标准ISO C99第6.2.5节第26段中,它声明void指针和字符指针将具有相同的表示和对齐要求(释义)。

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, ie (int) . 首先将它转换为类型,即(int)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM