C语言 什么时候需要在 C 中转换 void 指针?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/20469958/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
When is casting void pointer needed in C?
提问by Amoeba
I've been looking at Advanced Linux Programmingby Mitchell, Oldham and Samuel. I've seen in the section on pthreads something about void pointers and casting that confuses me.
我一直在看Mitchell、Oldham 和 Samuel 的Advanced Linux Programming。我在 pthreads 部分看到了一些关于 void 指针和强制转换的内容,这让我感到困惑。
Passing an argument to pthread_create(), they don't cast the pointer to a void pointer even though that is what the function expects.
将参数传递给 pthread_create(),它们不会将指针强制转换为 void 指针,即使这是函数所期望的。
pthread_create( &thread, NULL, &compute_prime, &which_prime );
Here, which_primeis of type int.
这里,which_prime是int类型。
But taking a value returned from the thread using pthread_join, they DO cast the variable to void pointer.
但是使用 pthread_join 从线程返回的值,他们确实将变量强制转换为 void 指针。
pthread_join( thread, (void*) &prime );
Here, primeis of type intagain.
这里,prime 又是int类型。
Why is casting done in the second instance and not in the first?
为什么在第二个实例中而不是在第一个实例中进行转换?
回答by Fred Foo
The second example is a good example of why casting to void*is usually a mistake. It should be
第二个例子很好地说明了为什么强制转换void*为通常是错误的。它应该是
void *primep = ′ // no cast needed
pthread_join(thread, &primep);
because pthread_jointakes a void**as its second argument. The void*only makes sure the bug passes the compiler because the void*is converted to void**automatically.
因为pthread_join将 avoid**作为它的第二个参数。在void*只有确保该bug通过编译,因为void*转换为void**自动。
So, when doyou need to cast to void*or back:
所以,当你需要投地void*或回:
- when working with pointers stored as integers (
(u)intptr_t); - when passing pointers to functions that have an incomplete prototype and take
void*(or take a different type of pointer and you havevoid*); that usually means functions taking a variable number of arguments such asprintf.
- 使用以整数形式存储的指针时 (
(u)intptr_t); - 将指针传递给具有不完整原型的函数并采用
void*(或采用不同类型的指针,而您有void*)时;这通常意味着函数采用可变数量的参数,例如printf.
回答by alk
No need to cast from or to a pointer to voidin C:
无需void在 C 中从或指向指向的指针:
6.3.2.3 Pointers
1 A pointer to voidmay be converted to or from a pointer to any incomplete or object type. A pointer to any incomplete or object type may be converted to a pointer to voidand back again; the result shall compare equal to the original pointer.
6.3.2.3 指针
1 指向void的指针可以与指向任何不完整或对象类型的指针相互转换。指向任何不完整或对象类型的指针可以转换为指向void的指针, 然后再返回;结果应与原始指针相等。
The only exceptions from this are
唯一的例外是
- when printing a pointer using the
"%p"conversion specifier as it's only defined forvoid *. - when copying a pointer's value from an
intptr_toruintptr_tback to avoid *.
- 使用
"%p"转换说明符打印指针时,因为它只为void *. - 将指针的值从
intptr_t或复制uintptr_t回void *.
回答by Asaf
In C, casting to void* from any pointer type and vice-versais done implicitly. There's no need for the cast in the second example.
在 C 中,从任何指针类型转换为 void* 和反之亦然是隐式完成的。在第二个示例中不需要演员表。
(Note that in C++ casting any pointer to void* is also done implicitly (except for function pointers and function-member / method pointers which cannot be cast to void*), but casting back requires an explicit cast.)
(请注意,在 C++ 中,任何指向 void* 的指针的转换也是隐式完成的(除了不能转换为 void* 的函数指针和函数成员/方法指针),但转换回需要显式转换。)
回答by Abhineet
As per the documentation,
根据文档,
int pthread_join(pthread_t thread, void **retval);
So, the pthread_jointakes a pointer to void*as its second argument. This is because,
因此,pthread_join将 apointer to void*作为其第二个参数。这是因为,
In pthread_join, you get back the address passed to pthread_exit by the finished thread. If you pass just a plain pointer, it is passed by value so you can't change where it is pointing to. To be able to change the value of the pointer passed to pthread_join, it must be passed as a pointer itself, that is, a pointer to a pointer.
在 pthread_join 中,您可以取回已完成线程传递给 pthread_exit 的地址。如果你只传递一个普通的指针,它是按值传递的,所以你不能改变它指向的位置。为了能够改变传递给 pthread_join 的指针的值,它必须作为一个指针本身传递,即一个指向指针的指针。
Now, to your question, "Why is casting done in the second instance and not in the first?"
In the first instance, i.e., pthread_create, it expects a void*as its fourth argument. So passing &which_primewould be implicitly converted to void*.
现在,对于您的问题,“为什么在第二个实例中而不是在第一个实例中进行转换?”在第一个实例中,即pthread_create,它期望 avoid*作为其第四个参数。因此传递&which_prime将隐式转换为void*.
In the second instance, i.e., pthread_join, it expects a void**and we are passing &primethere. So, the compiler will complain. So, to bypass the bug, the author passes a cast of void*which will be automatically converted to void**.
在第二种情况下,即 ,pthread_join它期望 avoid**并且我们正在&prime那里传递。所以,编译器会抱怨。因此,为了绕过该错误,作者传递了一个void*将自动转换为void**.
But this is not a good solution.
但这不是一个好的解决方案。
The Solution::
解决方案::
void* prime ; // make prime as void*
pthread_join( thread, &prime );
printf( "%" PRIxPTR "\n", (intptr_t)prime ) ;
// intptr_t instead of int to get an integer type
// that's the same size as a pointer
回答by Abhineet
I believe the same code has been referencedin other questions.
The answer in the second link explains:
第二个链接中的答案解释了:
It's not valid. It simply happens to work if sizeof(int) == sizeof(void *), which happens on many systems.
A void * is only guaranteed to be able to hold pointers to data objects.
Here is a C FAQ on the subject.
它无效。如果 sizeof(int) == sizeof(void *) ,它恰好可以工作,这在许多系统上都会发生。
void * 只能保证能够保存指向数据对象的指针。
这是有关该主题的 C 常见问题解答。
And the quoted text:
和引用的文字:
How are integers converted to and from pointers? Can I temporarily stuff an integer into a pointer, or vice versa?
Pointer-to-integer and integer-to-pointer conversions are implementation-defined (see question 11.33), and there is no longer any guarantee that pointers can be converted to integers and back, without change
Forcing pointers into integers, or integers into pointers, has never been good practice
整数如何与指针相互转换?我可以暂时将整数填充到指针中,反之亦然吗?
指针到整数和整数到指针的转换是实现定义的(请参阅问题 11.33),并且不再保证指针可以转换为整数并返回而无需更改
强制将指针转换为整数,或将整数转换为指针,从来都不是好的做法

