[英]Passing argument as int to thread - Warning: cast to pointer from integer different size
What is the difference between passing an argument to pthread_create as int instead of long? 将参数作为int而不是long传递给pthread_create有什么区别?
int pthread_create(pthread_t *restrict thread,
const pthread_attr_t *restrict attr,
void *(*start_routine)(void*), void *restrict arg);
I took the code from POSIX Threads Programming and it works only declaring the function argument as long 我从POSIX线程编程中获取了代码,并且仅在声明函数参数很长的情况下起作用
void *PrintHello(void *threadid) {
long tid;
tid = (long)threadid;
printf("Hello World! It's me, thread #%ld!\n", tid);
pthread_exit(NULL);
}
int main(int argc, char *argv[]) {
pthread_t threads[NUM_THREADS];
int rc;
long t;
for(t=0;t<NUM_THREADS;t++){
printf("In main: creating thread %ld\n", t);
rc = pthread_create(&threads[t], NULL, PrintHello, (void *)t);
if (rc){
printf("ERROR; return code from pthread_create() is %d\n", rc);
exit(-1);
}
}
/* Last thing that main() should do */
pthread_exit(NULL);
}
In this case, the issue has nothing to do with threads, but with the conversion between void *
and integer types. 在这种情况下,问题与线程无关,而与
void *
和整数类型之间的转换无关。 'c' allows you to freely convert across these types, but you have to pay attention to the sizes of the objects that you convert. 'c'允许您自由转换这些类型,但是您必须注意转换对象的大小。
For example, on x86 in 64-bit mode the size of the void*
is 64 bit (8 bytes). 例如,在64位模式下的x86上,
void*
的大小为64位(8字节)。 It is the same as the size of long int
. 它与
long int
的大小相同。 However, size of int
is 32 bits (4 bytes). 但是,
int
大小为32位(4个字节)。
So, conversion of an int
to (void*)
will sign-extend int to 64 bits and assign it to void. 因此,将
int
转换为(void*)
会将int符号扩展为64位,并将其分配给void。 Compiler gives you a warning, because sizes in the conversion are different but there is o violation of the standard here. 编译器会警告您,因为转换中的大小不同,但此处违反了标准。
Conversion back to int
from void *
will also generate a warning. 从
void *
转换回int
也会生成警告。 This conversion will loose upper 32 bits. 此转换将丢失高32位。 But it will convert it correctly to
int
, if the void *
itself was assigned from an int. 但是,这是正确转换为
int
,如果void *
本身是从一个int分配。 However, if you try to convert it to long
and the original int
was negative, you will get a completely different picture, it will not be the same as the original int
, all upper 32 bits will be a result of the original sign extension. 但是,如果您尝试将其转换为
long
且原始int
为负数,则会得到完全不同的图片,它将与原始int
,所有高32位将是原始符号扩展的结果。
To make the picture more interesting, it will work differently on different platforms. 为了使图片更有趣,它将在不同平台上以不同方式工作。 For example, on 32-bit platforms size of
long int
could be the same as the size of int
and the size of void*
. 例如,在32位平台上,
long int
的大小可能与int
的大小和void*
的大小相同。
Potentially size of long int
usually matches the size of void*
. long int
潜在大小通常与void*
的大小匹配。 At least it does for a few platforms. 至少它适用于一些平台。 Therefore this conversion is the safest one.
因此,这种转换是最安全的一种。
So, the best solution is to avoid such conversions when you write a cross-platform code. 因此,最好的解决方案是在编写跨平台代码时避免此类转换。
Your are treating the argument as a long
rather than a pointer to long
. 您正在治疗的参数为
long
,而不是一个指针long
。 This means you are depending on long
and void *
to have the same data size. 这意味着您要依赖
long
和void *
来拥有相同的数据大小。 If int
has a different size this could explain why it goes wrong. 如果
int
的大小不同,则可以解释为什么会出错。 In any case you should pass &t
in the argument and extract it accordingly as *threadid
: 无论如何,您都应在参数中传递
&t
并将其相应地提取为*threadid
:
void *PrintHello(void *threadid) {
long tid;
tid = *((long *)threadid);
printf("Hello World! It's me, thread #%ld!\n", tid);
pthread_exit(NULL);
}
int main(int argc, char *argv[]) {
pthread_t threads[NUM_THREADS];
static long tid[NUM_THREADS];
int rc;
long t;
for(t=0; t<NUM_THREADS; t++) {
printf("In main: creating thread %ld\n", t);
tid[t] = t;
rc = pthread_create(&threads[t], NULL, PrintHello, (void *)&tid[t]);
if(rc) {
printf("ERROR; return code from pthread_create() is %d\n", rc);
exit(-1);
}
}
/* Last thing that main() should do */
pthread_exit(NULL);
}
Update: Store thread IDs in array tid
. 更新:将线程ID存储在数组
tid
。
the following proposed code: 以下建议的代码:
perror()
) outputs the OPs error message AND the text reason the system thinks the error occurred to stderr
. perror()
)输出OPs错误消息和系统认为该错误发生的文本原因是stderr
。 int main( void )
so no messages from the compiler about unused parameters. int main( void )
因此编译器不会收到有关未使用参数的消息。 size_t
for the loop counter. size_t
用作循环计数器。 pthread_t
array to 0 so can be used for cleanup operations pthread_t
数组正确初始化(为0)为0,因此可用于清理操作 printf()
to expect a variable with type: size_t
printf()
的调用中的格式说明符,以期望变量类型为: size_t
main()
function properly wait for the threads to exit before the main()
function exits main()
函数退出之前让main()
函数正确等待线程退出 cleanup()
to properly cleanup any threads before exiting the program. cleanup()
在退出程序之前正确清理所有线程。 and now, the proposed code: 现在,建议的代码为:
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#define NUM_THREADS 20
void *PrintHello( void *arg )
{
size_t threadNum = (size_t)arg;
printf( "Hello World! It's me, thread #%lu!\n", threadNum );
pthread_exit( NULL );
}
void cleanup( pthread_t *threads )
{
for( size_t i=0; i<NUM_THREADS; i++ )
{
if( threads[i] )
{
pthread_join( threads[i], NULL );
}
}
}
int main( void )
{
pthread_t threads[ NUM_THREADS ] = {0};
for( size_t t = 0; t < NUM_THREADS; t++ )
{
printf( "In main: creating thread %ld\n", t );
if( pthread_create( &threads[t], NULL, PrintHello, (void *)t ) )
{
perror( "pthread_create() failed" );
cleanup( threads );
exit( EXIT_FAILURE );
}
}
cleanup( threads );
/* Last thing that main() should do */
pthread_exit( NULL );
}
here is the output from a typical run of the proposed code when no errors occur: 这是没有错误发生时,建议的代码的典型运行的输出:
In main: creating thread 0
In main: creating thread 1
Hello World! It's me, thread #0!
In main: creating thread 2
In main: creating thread 3
In main: creating thread 4
Hello World! It's me, thread #3!
In main: creating thread 5
Hello World! It's me, thread #4!
In main: creating thread 6
In main: creating thread 7
Hello World! It's me, thread #6!
Hello World! It's me, thread #5!
In main: creating thread 8
Hello World! It's me, thread #7!
In main: creating thread 9
Hello World! It's me, thread #8!
In main: creating thread 10
In main: creating thread 11
In main: creating thread 12
Hello World! It's me, thread #10!
Hello World! It's me, thread #9!
Hello World! It's me, thread #11!
In main: creating thread 13
In main: creating thread 14
Hello World! It's me, thread #13!
In main: creating thread 15
Hello World! It's me, thread #12!
Hello World! It's me, thread #14!
In main: creating thread 16
Hello World! It's me, thread #15!
In main: creating thread 17
In main: creating thread 18
In main: creating thread 19
Hello World! It's me, thread #19!
Hello World! It's me, thread #16!
Hello World! It's me, thread #17!
Hello World! It's me, thread #18!
Hello World! It's me, thread #1!
Hello World! It's me, thread #2!
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.