这是我的C代码:
int main()
{
void * ptr_void;
void ** ptr_2void;
ptr_void = ptr_2void;
return 0;
}
我只是想知道为什么这段代码有效?我已将(void *)
分配给(void **)
,编译器甚至在没有警告的情况下传递它。这种类型看起来不匹配。以下代码将(void **)
分配给(int *)
也可以。
int main()
{
int * ptr_int;
void ** ptr_2void;
ptr_int = ptr_2void;
return 0;
}
任何人都能弄明白(void *)
的确切内容是什么?
答案 0 :(得分:11)
void指针的类型转换为隐式指向任何其他数据类型的指针。编译器不会显示任何警告。类似地,从任何类型的指针到void *
的类型转换也可以在没有警告的情况下工作。
除了void指针之外,如果您尝试隐式地从一种指针类型转换为另一种指针类型,编译器将发出警告。
例如,考虑下面给出的代码,它会给你警告“assignment from incompatible pointer type
”。
int *intptr;
void *voidptr;
void **vvptr;
int intval=123;
voidptr=&intval;
vvptr=voidptr;
intptr=vvptr;
导致警告的代码行为intptr=vvptr;
,因为intptr
是integer pointer
而vvptr
是void **
类型的指针。它们都不是void *
指针,因而是一个警告。
为了避免此警告,您必须明确键入将void **
类型转换为int *
类型。如果您将行intptr=vvptr;
更改为intptr=(int *)vvptr;
,则编译器将不会显示警告。
答案 1 :(得分:4)
区分转换和强制转换非常重要。
转换将一种类型的值转换为另一种类型的值。强制转换是显式指定转换的运算符(由括号中的类型名称组成)。转换可以是显式的(由强制转换运算符指定)或隐式转换。大多数指针转换需要一个强制转换操作符涉及void*
的指针转换是例外。
任何指向对象类型(或指向不完整类型)的值都可以转换为void*
并返回其原始类型;保证结果指针与原始指针的比较等。
在赋值中(或者在将参数传递给函数时,或者在return
语句中)时,可以隐式地进行void*
的转换,而不使用强制转换运算符。
在您的第一个代码示例中:
void * ptr_void;
void ** ptr_2void;
ptr_void = ptr_2void;
允许分配,因为void**
可能会在没有演员的情况下转换为void*
。这里void**
没有什么特别之处;指向任何的指针可以在没有强制转换的情况下转换为void*
。 (void*
是通用指针类型; void**
不是通用指针到指针类型,实际上没有通用的指针到指针类型。)
在您的第二个代码示例中:
int * ptr_int;
void ** ptr_2void;
ptr_int = ptr_2void;
作业不有效;这是约束违规。 int*
和void**
之间没有隐式转换,因为这两种类型都不是void*
。任何符合标准的C编译器必须为分配发出诊断消息。在某些情况下,诊断可能是警告,编译器可能生成隐式转换,就像您编写了一个强制转换一样。在其他情况下,编译器可能需要其他选项才能使其诊断此违规。
请注意,上述内容不适用于函数指针。任何函数指针类型都可以转换(使用强制转换)到任何其他函数指针类型,将函数指针转换为void*
或反之亦然具有未定义的行为(尽管某些编译器可能支持)。
答案 2 :(得分:1)
void**
和void*
是不同的类型。 int*
和void**
也是不同的类型。但是正如Barmar所说,any data pointer type can be cast to/from void*.
这意味着你可以将int*
投射到void*
,但你无法将int*
投射到void**
,因为void**
没有同样的特殊财产。
gcc
应该发出警告:
warning: assignment from incompatible pointer type [enabled by default]
ptr_int = ptr_2void;
请参阅此问题:Passing to void** instead void* makes the compiler complain about types, why?
void *是一种可以隐式转换为任何对象的类型 指针类型。 void **不是 - 所以虽然你可以给一个char *分配一个 void *,你不能用char **和void **。
原因是它们是不兼容的类型:char **指向a char *,void **指向void *,因此它们的基类型不匹配。