简体   繁体   English

将参数作为int传递给线程-警告:从不同大小的整数强制转换为指针

[英]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. 这意味着您要依赖longvoid *来拥有相同的数据大小。 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: 以下建议的代码:

  1. cleanly compiles 干净地编译
  2. performs the desired functionality 执行所需的功能
  3. cleans up after itself, even when an error occurs 即使发生错误也可以自行清理
  4. properly (using perror() ) outputs the OPs error message AND the text reason the system thinks the error occurred to stderr . 正确(使用perror() )输出OPs错误消息和系统认为该错误发生的文本原因是stderr
  5. uses the signature: int main( void ) so no messages from the compiler about unused parameters. 使用签名: int main( void )因此编译器不会收到有关未使用参数的消息。
  6. Since a loop counter cannot be < 0, uses variable type size_t for the loop counter. 由于循环计数器不能小于0,因此将变量类型size_t用作循环计数器。
  7. properly initializes (to 0) the pthread_t array to 0 so can be used for cleanup operations pthread_t数组正确初始化(为0)为0,因此可用于清理操作
  8. Corrects the format specifiers in the calls to printf() to expect a variable with type: size_t 更正对printf()的调用中的格式说明符,以期望变量类型为: size_t
  9. Has the main() function properly wait for the threads to exit before the main() function exits main()函数退出之前让main()函数正确等待线程退出
  10. incorporates a new function: cleanup() to properly cleanup any threads before exiting the program. 合并了一个新函数: cleanup()在退出程序之前正确清理所有线程。
  11. uses appropriate horizontal spacing and vertical spacing for readability and ease of understanding. 使用适当的水平间距和垂直间距以提高可读性和易于理解。

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.

相关问题 警告:从不同大小的 integer 转换为指针 - Warning: cast to pointer from integer of different size 警告:从指针转换为不同大小的整数[-Wpointer-to-int-cast] - warning: cast from pointer to integer of different size [-Wpointer-to-int-cast] 警告:从指针转换为不同大小的整数 [-Wxpointer-to-int-cast] - warning: cast from pointer to integer of different size [-Wxpointer-to-int-cast] gcc.exe 警告从指针转换为不同大小的整数 [-Wpointer-to-int-cast] - gcc.exe warning cast from pointer to integer of different size [-Wpointer-to-int-cast] 警告:传递&#39;memcpy&#39;的参数1会使指针从整数开始而无需强制转换 - warning: passing argument 1 of ‘memcpy’ makes pointer from integer without a cast 警告传递&#39;finder&#39;的参数2使指针从整数开始而无需强制转换 - Warning passing argument 2 of 'finder' makes pointer from integer without a cast 警告:传递&#39;fopen&#39;的参数2会使指针从整数开始而无需强制转换 - warning: passing argument 2 of ‘fopen’ makes pointer from integer without a cast 警告:传递“ quicksort”的参数1会使指针从整数开始而无需强制转换 - warning: passing argument 1 of 'quicksort' makes pointer from integer without a cast 警告:传递&#39;calcFx&#39;的参数2将使指针产生整数而不进行强制转换 - warning: passing argument 2 of 'calcFx' makes integer from pointer without a cast 警告:传递&#39;strcpy&#39;的参数1会使指针从整数开始而不进行强制转换 - warning: passing argument 1 of ‘strcpy’ makes pointer from integer without a cast
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM