![](/img/trans.png)
[英]a value of type “void” cannot be assigned to an entity of type "void(*)(struct *Queue, int)
[英]why (void **) type can be assigned to (void *) or (int *)?
这是我的C代码:
int main()
{
void * ptr_void;
void ** ptr_2void;
ptr_void = ptr_2void;
return 0;
}
我只是想知道为什么这段代码有效? 我已经(void *)
分配了(void *)
(void **)
,编译器甚至在没有警告的情况下传递它。 这种类型看起来不匹配。 以下代码(void **)
分配给(int *)
也有效。
int main()
{
int * ptr_int;
void ** ptr_2void;
ptr_int = ptr_2void;
return 0;
}
任何人都能弄清楚什么是(void *)
东西?
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;
to intptr=(int *)vvptr;
然后编译器不会显示警告。
区分转换和演员是很重要的。
转换将一种类型的值转换为另一种类型的值。 强制转换是显式指定转换的运算符(由括号中的类型名称组成)。 转换可以是显式的(由强制转换运算符指定)或隐式转换。 大多数指针转换需要一个强制转换操作符 涉及void*
指针转换是例外。
任何指向对象的类型(或指向不完整的类型)的值都可以转换为void*
并返回其原始类型; 保证结果指针与原始指针的比较相等。
在赋值中(或者将参数传递给函数或在return
语句中),可以隐式地执行到void*
的转换,而不使用强制转换运算符。
在您的第一个代码示例中:
void * ptr_void;
void ** ptr_2void;
ptr_void = ptr_2void;
允许赋值是因为void**
可以在void**
转换的情况下转换为void*
。 这里没有什么特别的void**
; 指向任何东西的指针可以在没有强制转换的情况下转换为void*
。 ( void*
是通用指针类型; void**
不是通用的指针指针类型,实际上没有通用的指针指针类型。)
在您的第二个代码示例中:
int * ptr_int;
void ** ptr_2void;
ptr_int = ptr_2void;
转让无效 ; 这是违反约束的行为 。 int*
和void**
之间没有隐式转换,因为这两种类型都不是void*
。 任何符合要求的C编译器都必须为赋值发出诊断消息。 在某些情况下,诊断可能是一个警告,编译器可能会生成隐式转换,就像您编写了一个强制转换一样。 在其他情况下,编译器可能需要其他选项才能使其诊断此违规。
请注意,上述内容不适用于函数指针。 任何函数指针类型都可以转换(使用强制转换)到任何其他函数指针类型,将函数指针转换为void*
,反之亦然,具有未定义的行为(尽管某些编译器可能支持)。
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;
看到这个问题: 传递给void **而不是void *会让编译器抱怨类型,为什么?
void *是一种可以隐式转换为任何对象指针类型的类型。 void **不是 - 所以虽然你可以将char *分配给void *,但你不能对char **和void **做同样的事情。
原因是它们是不兼容的类型:char **指向char *,void **指向void *,因此它们的基类型不匹配。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.