通过void修改任何数据指针是否合法**

通过void **访问指针类型是否合法?

我已经查看了指针别名的标准引用,但我仍然不确定这是否是合法的C:

 int *array; void **vp = (void**)&array; *vp = malloc(sizeof(int)*10); 

琐碎的例子,但它适用于我看到的更复杂的情况。

由于我通过类型不是int *char *的变量访问int * ,所以它似乎不合法。 我不能就此得出一个简单的结论。

有关:

  • C是否具有通用的“指针指针”类型?
  • C-FAQ问题4.9

指向不同类型的指针可以具有不同的大小。

您可以将指向任何类型的指针存储到void * ,然后您可以将其恢复,但这意味着void *必须足够大以容纳所有其他指针。

通常,不允许处理持有int *的变量,就像它确实是一个void *一样。

另请注意,执行转换(例如,转换为int * malloc的结果)与处理包含int *的内存区域完全不同,就像它包含void * 。 在第一种情况下,如果需要,编译器将被告知转换,而在第二种情况下,您将向编译器提供错误信息。

然而,在X86上,它们通常具有相同的大小,如果您只是使用指向数据的指针,那么您就是安全的(尽管指向函数的指针可能不同)。

关于通过void *char *完成的任何写操作的别名都可以改变任何对象,因此编译器必须尽可能考虑别名。 然而,在你的例子中,你正在编写一个void ** (一个不同的东西),编译器可以自由地忽略对int *潜在别名效果。

void **具有特定类型 (指向指向void的指针)。 即指针的基础类型是“指针到空”

存储指向int的指针时,不存储类似指针的值。 需要强制转换是一个强有力的指标,你所做的不是标准定义的行为(事实并非如此)。 然而,有趣的是,你可以使用常规的void*来来往往,它将表现出定义的行为。 换句话说,这个:

 #include  #include  int main() { int *array; void *vp = &array; int **parray = vp; *parray = malloc(sizeof(int)*10); } 

是合法的。 如果我删除演员并使用apple llvm 4.2(clang),你原来的例子甚至都不会编译 ,这恰好归因于不兼容的指针类型,即问题的主题。 具体错误是:

“不兼容的指针类型使用’int **’类型的表达式初始化’void **’”

这是理所当然的。

您的代码可能适用于某些平台,但它不可移植。 原因是C没有指向指针类型的通用指针。 在void *的情况下,标准明确允许它与其他指向完全/不完整类型的指针之间的转换,但这不是void **的情况。 这意味着在您的代码中,编译器无法知道*vp的值是否从void *以外的任何类型转换,因此除了您自己显式转换之外,不能执行任何转换。

考虑以下代码:

 void dont_do_this(struct a_t **a, struct b_t **b) { void **x = (void **) a; *x = *b; } 

编译器不会抱怨*x = *b行中从b_t *void *的隐式b_t * ,即使该行试图在仅应放置指向a_t指针的地方放置指向a_t指针。 错误实际上是在前一行中,它将“指向指向a_t的指针的位置的指针”转换为“指向指向任何东西的指针的地方的指针”。 这就是没有隐式演员的原因。 有关指向算术类型的指针的类似示例,请参阅C FAQ 。

然后,即使它关闭编译器警告,你的演员也是危险的,因为并非所有指针类型都可能具有相同的内部表示/大小(例如void **int * )。 要使代码在所有情况下都能正常工作,您必须使用中间void *

 int *array; void *varray = array; void **vp = &varray; *vp = malloc(sizeof(int) * 10);