我错过了几个课程,并没有真正理解流动的演讲幻灯片关于void指针的例子。
在“no,no,no”这一行中,为什么我们不能因为P被分配了一个真正的指针类型q而不能使用P?
在“??”行中,将指针强制转换为整数是否合法? (我认为它可以编译,因为C不会检查演员表,但不知道它会得到什么样的结果
Conversion of integer pointer to integer
他投了* p = 10;
a =(int)p;
并且有人回答说a将是一个非常大的价值。
但在我的情况下,是(int)* p ...是否与我上面给出的例子相同?
答案 0 :(得分:6)
“void *”的意思是“这个值是指向某个东西的指针,但我不会告诉你它指向的是什么”。从这个陈述开始,一切都有意义。
所以应该清楚的是,你不能取消引用空白*,因为没有人告诉你它指的是什么!如果您不知道它是指向int,char还是某个struct,那么如果您取消引用它,您认为会发生什么?
在C中,您可以为任何指针指定void *,例如指定为int *。编译器不知道 void *指向的内容,但是当你写r = p时;编译器说“我希望你知道你在做什么,我相信你。”(同样情况下的C ++编译器不信任你)。如果void * p确实指向了int,那么一切都很好。否则,事情或多或少都会变坏。
??一个是错的。你不能解除引用* p。不管你事后做什么,* p是不允许的。并且没有指针被转换为整数。尝试取消引用指针,这是不允许的。取消引用的结果可能没有任何用处,因为你不知道p指向什么,所以你没有什么用于转换为int。
现在*(int *)中发生了什么p:p是一个void * - 指向某个东西的指针,但是你不知道它指向的是什么。 (int *)p是强制转换:p转换为int *。这意味着编译器会相信(int *)p指向一个int - 可能是也可能不是。 *(int *)p取消引用int *:总的来说,你说服编译器p指向一个int,并读取p希望指向的int。如果p确实指向了int,那很好。如果p没有指向int,那你就麻烦了。
答案 1 :(得分:3)
Void指针是特定的指针,没有与之关联的数据类型。您必须将它们重新转换为特定类型(即e *:int *)才能访问其内容。
澄清您的具体要点:
1)虽然p可能有一个指针地址,但它没有与之关联的特定数据类型(数据类型是访问内容所必需的)
2)此操作的结果可能是内容的确定性。我不建议这是一个好习惯。
3)这告诉编译器将void指针视为整数指针。因此,它“知道”与之关联的数据类型,并将其作为int进行访问。
答案 2 :(得分:3)
在“不,不,不”这一行中,为什么我们不能因为P已经不顺从P. 分配了一个真正的指针类型q?
int a =2, *q = a, *r; //line 1
void *p; //line 2
p = q; // line 3
r = p; // line 4
使用上面的第3行,您将指针q
指定给p
。但它并没有改变p
的类型 - 它仍然是一个无效指针。所以你不能取消引用它。所以以下内容无效:
printf("%d\n", *p); // p is a void pointer - dereferencing here is illegal
或者,您可以这样做:
printf("%d\n", *((int*) p)); // p is a void pointer
以上是有效的。因为,我们会在解除引用之前将p
转换为int *
。考虑一个例子,
void func(void *p)
{
// what's `p` point to here?
}
int main(void)
{
int i = 5;
long x = 10;
void *p;
p = &i; // line 1
p = &x; //line 2
func(p);
}
您可以注释掉line1或line2,但func()
中是否有p
来指示long
数据或int
数据?这与你的情况没什么不同。
但是在访问其指向的数据之前,始终需要从void *
到type *
(数据指针)的转换。请注意,它不能是任何数据指针。例如,
int i = 42;
float f = 4.0;
void *p = &f;
printf("%d\n", *((int*))p); // wrong!
这是非法的。 p
指向float *
。解除引用,好像它指向int
数据是错误的。
在“??”行中,将指针强制转换为整数是否合法?
printf("%d\n", (int) *p);
由于p
是void*
,因此首先不允许取消引用。解除引用后的强制转换不会改变任何内容,解除引用也是非法的。
如果您将指针本身转换为:
printf("%d\n", (int)p);
这在C中具有实现定义的行为.C还为整数到指针转换提供intptr_t
/ uintptr_t
类型。
答案 3 :(得分:1)
如果指针p
的类型为void *
,则表达式*p
的类型为void
,void
类型没有值 1 ;这就是为什么你必须将指针转换为"真正的"取消引用它之前的指针类型。
指针和整数可以相互转换,但不保证这些值有意义。但是,这不是标记为??
的行正在做的事情;它试图取消引用p
并投射结果,但由于p
是指向void
的指针,因此不允许这样做。
表达式*((int *) p)
从指向p
的指针转换void
到指向int
的指针并取消引用结果。由于p
指向a
,因此评估为a
(2
)的值。
<小时/> 1。
void
类型是不完整的类型,无法完成。