C void指针算术

时间:2013-03-05 16:13:55

标签: c pointers

我认为在gcc中,void *和char *在指针运算方面的处理方式相同,即void *“指向”内存中的单个字节,因此以下代码

void *p;
p = malloc(sizeof(void));
printf("%p %p\n",p,p+1);

确实会返回0x984a008 0x984a009。类似地,void **指向一个指针,因此增加1实际上意味着增加4个字节(在32位OS上),即

void **p;
p = (void **) malloc(sizeof(void *));
printf("%p %p\n",p,p+1);

返回0x984a008 0x984a00c。但是,以下代码让我感到困惑

void **p, *p1;
p = (void **) malloc(sizeof(void *));
p1 = (void **) p;
printf("%p %p\n",p1,p1+1);

因为它再次返回0x984a008 0x984a009。这里发生了什么?

5 个答案:

答案 0 :(得分:7)

暂时忽略void指针算术的可能未定义行为......

p1的类型为void *

您不能通过为其指定不同类型的值来更改变量的类型。 p1将始终保持void *

分配给它的任何不同类型的表达式将隐式地强制转换为void *(如果不能,则给出错误)。

因此它与第一个例子基本相同。

修改

据我所知,从一种指针类型转换为另一种指针类型实际上并没有做任何事情,其主要目的是进行类型检查。

指针只是一个内存地址,一个数字,所以内存看起来像:(分配后)

  p1       p2
void *   void** <- these types are fixed and known during compilation
------   ------
|1234|   |1234|         at address 1234 = the 4 bytes from malloc
------   ------
  ^
  |
this value is the only thing that will change by assigning p1 to a different value

答案 1 :(得分:3)

您应该使用char *而不是void *,因为指向void的指针是gcc扩展名。

char *p1 = /* ... */;

printf("%p %p\n", p1, p1+1);

无论点p如何,p上的指针算术使用char *类型(不是char **)。

如果你写:

char *p1 = /* ... */;

printf("%p %p\n", p1, (char**)p1+1);

指针算术使用char **

答案 2 :(得分:2)

使用void *进行操作时,增量为1.当您使用void **时,它是指针的大小。

在让您感到困惑的操作中,您的void *强制转换为void **的行为将被隐式恢复为void *。就好像你这样做了:

long a, b, c;
c = a + (int) b;

您将b投射到int,但之后您希望使用long进行操作,因此它会被投回。

答案 3 :(得分:1)

void指针不能递增。这是未定义的行为。

相关问题: Increment void pointer by one byte? by two?

答案 4 :(得分:0)

我知道我在一年后发帖,但我碰巧遇到了这个问题,这引起了我的兴趣。

我同意@Dukeling你不能仅仅通过投射来改变变量的类型。但它似乎取决于编译器认为void的内容。以此示例程序为例,查看结果输出。请注意,vpvp2之间的唯一区别是sizeof()的{​​{1}}部分。

编译于:malloc()
编译行:gcc (Debian 4.7.2-5) 4.7.2

gcc -o void_test void_test.c

提供以下输出:

#include <stdio.h>
#include <stdlib.h>

int main(int argc, char **argv) {
  void *vp, *vp2;

  printf("sizeof(void)   = %d\n", sizeof(void));
  printf("sizeof(void *) = %d\n", sizeof(void *));
  printf("sizeof(char)   = %d\n", sizeof(char));
  printf("sizeof(char *) = %d\n\n", sizeof(char *));

  vp = (void *) malloc(sizeof(void));
  vp2 = (void *) malloc(sizeof(void *));

  printf("vp    = %p\n", vp);
  printf("vp+1  = %p\n", vp+1);
  printf("vp2   = %p\n", vp);
  printf("vp2+1 = %p\n", vp2+1);

  return 0;
}