将void指定给双指针

时间:2014-05-09 07:11:52

标签: c void

我需要了解为什么将void*分配给int**会有效,但是在打印int**的值时,它将无效。这是代码:

int k = 3;
int *l = &k;
void *a = l; 
int **c = a; // if I assign, &a, the below line work, but get warning: incompatible
             // pointer type.
printf("%d", **c); // Code break;

但这一行

printf("%d", *c); // will work, but get warning "%d expect int but of type int *".

更新:我在OOC book中看到了这种类型的代码:作者这样做:

struct Class {
   size_t size;
   int (*differ)(const void *self, const void *b);
   ..... Some more code ....

};

int differ(const void *self, const void *b) {
  // Note this line
  const struct Class **cp = self;
  assert(self && *cp && (*cp)->differ);
  return (*cp)->differ(self, b);
}

2 个答案:

答案 0 :(得分:3)

你有这种情况:

+---+
| l | --\
+---+    \     +---+
          >--> | k |
+---+    /     +---+
| a | --/
+---+

即。 la都直接指向k

然后你做

int **c = a;

你使c指向a所指向的内容(即它与执行int **c = &k相同),但是你声明c是一个指针指向int的指针,但指向int。这意味着使用单个解除引用(*c)可以获得k的值,当您使用双重引用(**c)时,可以使用k的值作为指针(事实并非如此)。

我认为你真正想要的是这种情况:

+---+     +---+     +---+
| a | --> | l | --> | k |
+---+     +---+     +---+

你将通过

获得
void *a = &l;

然后使用c作为指针指针将起作用,因为a是指向指针的指针。


如果您继续第一个方案,那么

int   k;
int  *l = &k;
void *a = l;

然后再做

int **c = (int **) &a;  // The typecast is needed

然后你有以下情况:

          +---+
          | l | --\
          +---+    \     +---+
                    >--> | k |
+---+     +---+    /     +---+
| c | --> | a | --/
+---+     +---+

这样可行,因为c实际上指向某事物指针的指针。

答案 1 :(得分:2)

这就是为什么你必须小心void*指针。您可以为它们分配任何指针,并可以将它们分配给任何其他指针。即使它没有意义(如你的例子)。

当您指定int **c = a时,您已经犯了一个错误,我认为您已经意识到这一点。您已更改了间接级别(a来自int*,但您已将其分配给int**),但未提取其他地址-of(&)。

您的程序失败的原因相同,如果您删除了void* a,而是尝试了此操作,则会失败。

int k = 3;
int *l = &k;
int **c = l;    // Error - wrong level of indirection.

这是低级别C.只是因为编译器让你做某事并不意味着它会起作用。

这个问题的解决方案是:不要这样做