对C

时间:2015-12-06 21:56:28

标签: c pointers void-pointers generic-programming

我错过了几个课程,并没有真正理解流动的演讲幻灯片关于void指针的例子。

  1. 在“no,no,no”这一行中,为什么我们不能因为P被分配了一个真正的指针类型q而不能使用P?

  2. 在“??”行中,将指针强制转换为整数是否合法? (我认为它可以编译,因为C不会检查演员表,但不知道它会得到什么样的结果

  3. 在这个例子中

    Conversion of integer pointer to integer
    他投了* p = 10;           a =(int)p; 并且有人回答说a将是一个非常大的价值。 但在我的情况下,是(int)* p ...是否与我上面给出的例子相同?

    1. 在最后一行,我对表达感到困惑。 *((int *)p)实际上是= p吗? 谢谢!
    2. enter image description here

      enter image description here

4 个答案:

答案 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);

由于pvoid*,因此首先不允许取消引用。解除引用后的强制转换不会改变任何内容,解除引用也是非法的。

如果您将指针本身转换为:

printf("%d\n", (int)p);

这在C中具有实现定义的行为.C还为整数到指针转换提供intptr_t / uintptr_t类型。

答案 3 :(得分:1)

如果指针p的类型为void *,则表达式*p的类型为voidvoid类型没有值 1 ;这就是为什么你必须将指针转换为"真正的"取消引用它之前的指针类型。

指针和整数可以相互转换,但不保证这些值有意义。但是,这不是标记为??的行正在做的事情;它试图取消引用p并投射结果,但由于p是指向void的指针,因此不允许这样做。

表达式*((int *) p)从指向p的指针转换void到指向int的指针并取消引用结果。由于p指向a,因此评估为a2)的值。

<小时/> 1。 void类型是不完整的类型,无法完成。