5

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

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

确实返回0x984a008 0x984a009。同样, void ** 指向一个指针,因此递增 1 实际上意味着递增 4 个字节(在 32 位操作系统上),即

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。这里发生了什么?

4

5 回答 5

7

Ignoring the possible undefined behaviour of void pointer arithmetic for the moment...

The type of p1 is void *.

You can't change a variable's type by assigning a value of a different type to it. p1 will always stay void *.

Any expression of a different type assigned to it will implicitly be cast to void * (or give an error if it can not).

Thus it's essentially the same as the first example.

EDIT:

As far as I know, casting from one pointer type to another doesn't actually do anything, its main purpose is for type-checking.

A pointer is just a memory address, a number, so essentially the memory looks something like: (post-assignment)

  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
于 2013-03-05T16:29:26.157 回答
3

You should use char * instead of void *, since arithmetic on pointer to void is a gcc extension.

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

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

Whatever points p, the pointer arithmetic on p uses char * type (not char **).

If you write:

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

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

Pointer arithmetic uses char **.

于 2013-03-05T16:30:21.830 回答
2

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

在使您感到困惑的操作中,您的void *演员 tovoid **被隐式地重新转换为void *. 就好像你这样做了:

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

你投到bint但是你想用 a 操作long,所以它被投回了。

于 2013-03-05T16:28:05.737 回答
1

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

相关问题: 将 void 指针增加一个字节?两个?

于 2013-03-05T16:25:37.207 回答
0

我知道我要在一年多后发帖,但我碰巧遇到了这个问题,这让我很感兴趣。

我同意@Dukeling 的观点,即您不能仅通过强制转换来更改变量的类型。但这似乎取决于编译器认为void是什么。以这个示例程序为例,看看结果输出。vp请注意,和之间的唯一区别vp2是.sizeof()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;
}

给出以下输出:

$ ./void_test 
sizeof(void)   = 1
sizeof(void *) = 8
sizeof(char)   = 1
sizeof(char *) = 8

vp    = 0x1ee3010
vp+1  = 0x1ee3011
vp2   = 0x1ee3010
vp2+1 = 0x1ee3031
于 2014-06-27T14:24:52.543 回答