对 C 中的指针和泛型(void)指针感到困惑
Confused about the pointers and generic(void) pointers in C
我错过了几个 类,并且不太理解流畅的讲座幻灯片中关于 void 指针的示例。
在"no,no,no"行中,既然P已经被赋予了一个真正的指针类型q,为什么我们不能推导P?
在“??”行中,将指针转换为整数是否合法? (我认为它可以编译,因为 C 不检查转换,但不知道它会得到什么样的结果
在这个例子中
Conversion of integer pointer to integer
他投了 *p = 10;
a = (整数)p;
有人回答说 a 将是一个非常大的值。
但就我而言,是 (int) *p... 是否与我上面给出的示例相同?
- 在最后一行,我对表达感到困惑。 * ((int *)p) 实际上 = p 吗?
谢谢!
空指针特指没有关联数据类型的指针。您必须将它们重新转换为特定类型(即:int*)才能访问其内容。
澄清您的具体观点:
1) 虽然 p 可能有一个指针地址,但它没有与之关联的特定数据类型(访问内容需要数据类型)
2) 此操作的结果可能对内容具有确定性。我不推荐这是一个好习惯。
3) 这是告诉编译器将 void 指针视为整数指针。因此,它 "knows" 与之关联的数据类型,并将其作为 int 进行访问。
"void*" 表示 "this value is a pointer to something, but I'm not telling you what it points to"。从这句话开始,一切都说得通了。
所以应该清楚您不能取消对 void* 的引用,因为没有人告诉您它指向什么!如果您不知道它是指向一个 int、一个 char 还是某个结构,您认为如果您取消引用它会发生什么?
在 C 中,您可以将 void* 分配给任何指针,例如分配给 int*。编译器 不知道 void* 指向什么,但是当你写 r = p;编译器说 "I hope you know what you are doing, I trust you. " (同样情况下的 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,你就有麻烦了。
In the line "no,no,no", why we cannot deference P since P has been
assigned a real pointer type 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);
}
您可以注释掉第 1 行或第 2 行,但无论如何 func()
中是否存在以了解 p
是指向 long
数据还是 int
数据?这与您的情况没有什么不同。
但是在访问其指向的数据之前,始终需要从 void *
到 type *
(数据指针)的转换。请注意,它不能是 any 数据指针。例如,
int i = 42;
float f = 4.0;
void *p = &f;
printf("%d\n", *((int*))p); // wrong!
这是非法的。 p
指向一个 float *
。取消引用就好像它指向 int
数据是错误的。
In the line " ?? ", is it legal to cast a pointer to a integer?
printf("%d\n", (int) *p);
因为 p
是一个 void*
,所以一开始就不允许取消引用。取消引用后的转换不会改变任何内容,并且取消引用是非法的。
如果您要像这样转换指针本身:
printf("%d\n", (int)p);
这在 C 中具有 实现定义的 行为。C 还提供 intptr_t
/uintptr_t
类型用于整数到指针的转换。
如果指针 p
的类型为 void *
,则表达式 *p
的类型为 void
,而 void
类型没有值1;这就是为什么在取消引用之前必须将指针转换为 "real" 指针类型的原因。
指针和整数可以相互转换,但不保证这些值是有意义的。但是,这不是标记为 ??
的行所做的;它试图取消引用 p
并转换结果,但由于 p
是指向 void
的指针,这是不允许的。
表达式 *((int *) p)
将 p
从指向 void
的指针强制转换为指向 int
的指针并取消引用结果。由于 p
指向 a
,因此计算结果为 a
(2
).
1。 void
类型是不完整类型,无法完成。
我错过了几个 类,并且不太理解流畅的讲座幻灯片中关于 void 指针的示例。
在"no,no,no"行中,既然P已经被赋予了一个真正的指针类型q,为什么我们不能推导P?
在“??”行中,将指针转换为整数是否合法? (我认为它可以编译,因为 C 不检查转换,但不知道它会得到什么样的结果
在这个例子中
Conversion of integer pointer to integer
他投了 *p = 10;
a = (整数)p;
有人回答说 a 将是一个非常大的值。
但就我而言,是 (int) *p... 是否与我上面给出的示例相同?
- 在最后一行,我对表达感到困惑。 * ((int *)p) 实际上 = p 吗? 谢谢!
空指针特指没有关联数据类型的指针。您必须将它们重新转换为特定类型(即:int*)才能访问其内容。
澄清您的具体观点:
1) 虽然 p 可能有一个指针地址,但它没有与之关联的特定数据类型(访问内容需要数据类型)
2) 此操作的结果可能对内容具有确定性。我不推荐这是一个好习惯。
3) 这是告诉编译器将 void 指针视为整数指针。因此,它 "knows" 与之关联的数据类型,并将其作为 int 进行访问。
"void*" 表示 "this value is a pointer to something, but I'm not telling you what it points to"。从这句话开始,一切都说得通了。
所以应该清楚您不能取消对 void* 的引用,因为没有人告诉您它指向什么!如果您不知道它是指向一个 int、一个 char 还是某个结构,您认为如果您取消引用它会发生什么?
在 C 中,您可以将 void* 分配给任何指针,例如分配给 int*。编译器 不知道 void* 指向什么,但是当你写 r = p;编译器说 "I hope you know what you are doing, I trust you. " (同样情况下的 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,你就有麻烦了。
In the line "no,no,no", why we cannot deference P since P has been assigned a real pointer type 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);
}
您可以注释掉第 1 行或第 2 行,但无论如何 func()
中是否存在以了解 p
是指向 long
数据还是 int
数据?这与您的情况没有什么不同。
但是在访问其指向的数据之前,始终需要从 void *
到 type *
(数据指针)的转换。请注意,它不能是 any 数据指针。例如,
int i = 42;
float f = 4.0;
void *p = &f;
printf("%d\n", *((int*))p); // wrong!
这是非法的。 p
指向一个 float *
。取消引用就好像它指向 int
数据是错误的。
In the line " ?? ", is it legal to cast a pointer to a integer?
printf("%d\n", (int) *p);
因为 p
是一个 void*
,所以一开始就不允许取消引用。取消引用后的转换不会改变任何内容,并且取消引用是非法的。
如果您要像这样转换指针本身:
printf("%d\n", (int)p);
这在 C 中具有 实现定义的 行为。C 还提供 intptr_t
/uintptr_t
类型用于整数到指针的转换。
如果指针 p
的类型为 void *
,则表达式 *p
的类型为 void
,而 void
类型没有值1;这就是为什么在取消引用之前必须将指针转换为 "real" 指针类型的原因。
指针和整数可以相互转换,但不保证这些值是有意义的。但是,这不是标记为 ??
的行所做的;它试图取消引用 p
并转换结果,但由于 p
是指向 void
的指针,这是不允许的。
表达式 *((int *) p)
将 p
从指向 void
的指针强制转换为指向 int
的指针并取消引用结果。由于 p
指向 a
,因此计算结果为 a
(2
).
1。
void
类型是不完整类型,无法完成。