这是我的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 *)
东东?
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 *
指针,因此是一个警告。
为了避免这种警告,你必须显式地输入cast void **
输入到 int *
类型。如果你改变了这条线 intptr=vvptr;
至 intptr=(int *)vvptr;
然后编译器不会显示警告。
区分a是很重要的 转变 和a 投。
转换将一种类型的值转换为另一种类型的值。强制转换是一个运算符(由括号中的类型名称组成),它明确指定转换。转换可以是显式的(由强制转换运算符指定)或隐式转换。大多数指针转换需要强制转换操作符;指针转换涉及 void*
是例外。
可以将任何指向对象的指针类型(或指向不完整的指针类型)的值转换为 void*
并回到原来的类型;保证结果指针与原始指针的比较等于。
在赋值中(或者在将参数传递给函数时,或者在函数中传递 return
声明),转换或转换 void*
可以隐式地完成,没有强制转换操作符。
在您的第一个代码示例中:
void * ptr_void;
void ** ptr_2void;
ptr_void = ptr_2void;
允许分配,因为a 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**
也是不同的类型。但正如巴马尔所说, 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 **指向a
char *,void **指向void *,因此它们的基类型不匹配。