C语言 从不同大小的整数转换为指针,pthread 代码

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/19527965/
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

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-02 07:48:00  来源:igfitidea点击:

cast to pointer from integer of different size, pthread code

cpthreads

提问by Ruaa Brkat

I have this code for matrix multiplication, using pthreads, but I get the error "cast to pointer from integer of different size"

我有这个矩阵乘法的代码,使用 pthreads,但我收到错误“从不同大小的整数转换为指针”

I don't know what is wrong.I am new to pthread, and this is what I have made so far:

我不知道出了什么问题。我是 pthread 的新手,这是我迄今为止所做的:

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <sys/time.h>
#include <pthread.h>

#define NTHREADS 4

int dim ;
pthread_mutex_t m;       /* Mutex protecting the sum value */
pthread_t thread_id[NTHREADS];  /* Thread ids */
float **A, **B, **C;

void *prod (void *s){
    int *id=(int *)s;
    int idd=*id;


    /* Define local variables */
    int i,j,k, start, end, len ;
    float **Aa, **Bb, **Cc;

    start = dim*idd;       /* Start of this threads slice of the vectors */
    end   = start + dim;      /* End of the slice */


    for (i = 0 ; i < dim; i++)
    {
        for (j = 0;  j < dim; j++)
        {
            Cc[i][j] = 0;
            for (i=start; i<end ; i++) {

                Cc[i][j] += Aa[i][k] * Bb[k][j];
            }
        }
    }
    pthread_mutex_lock (&m);     /* Lock the mutex */
    C[i][j] += Cc[i][j];                /* Update the shared variable */
    pthread_mutex_unlock (&m);   /* Unlock the mutex */

    pthread_exit(NULL);            /* Done! */
}

int main ( int argc, char *argv[] )
{
    void *status;
    float **A, **B, **C;
    int i,j,k;

    if ( argc == 2)
        dim = atoi(argv[1]); // get the dimension of the matrix
    // from the command prompt

    else
        dim = 128;



    A = (float **)malloc(sizeof(float*)*dim);
    B = (float **)malloc(sizeof(float*)*dim);
    C = (float **)malloc(sizeof(float*)*dim);

    for (i = 0 ; i < dim; i++)
    {
        A[i] = (float *)malloc(sizeof(float)*dim);
        B[i] = (float *)malloc(sizeof(float)*dim);
        C[i] = (float *)malloc(sizeof(float)*dim);
    }

    for (i=0; i<dim; i++)
    {
        for (j = 0 ; j < dim; j++)
        {
            A[i][j]=rand();
            B[i][j]=rand();
        }
    }

    struct timeval t1, t2;
    gettimeofday(&t1, NULL);

    // you need to parallelize this
    // perform the multiplication
    for(i=0;i<NTHREADS;i++) {

        pthread_create(&thread_id[i], NULL, prod, (void *)i);
    }
    /* Wait on the other threads */
    for(i=0;i<NTHREADS;i++) {
        pthread_join(thread_id[i], &status);
    }

    gettimeofday(&t2, NULL);

    double t = (t2.tv_sec - t1.tv_sec) + (t2.tv_usec - t1.tv_usec ) / 1000000.0;
    // take the difference and report it in seconds
    printf("execution time %f seconds\n",t);
}

the error at this line:

这一行的错误:

pthread_create(&thread_id[i], NULL, prod, (void *)i); 

回答by Giuseppe Pes

You are wrongly using an hack to pass an integer to a thread. The idea behind what you are doing is an integer is 4 bytes and a pointer is 4 bytes in x86_32 (8 bytes in x86_64) so I can convert an integer type to a pointer type and then convert it back to an int type without losing any data. This works in the majority of the scenarios, but there is not guarantee that a pointer and an integer have the same size. The C standard does notspecify this.

您错误地使用 hack 将整数传递给线程。你在做什么背后的想法是一个整数是 4 个字节,一个指针是 4 个字节在 x86_32 中(在 x86_64 中是 8 个字节),所以我可以将整数类型转换为指针类型,然后将其转换回 int 类型而不会丢失任何数据。这适用于大多数情况,但不能保证指针和整数具有相同的大小。C 标准没有规定这一点。

The compiler returns a warning because you are converting an intto void *which may have different size, ( but in fact in your machine they have the same size).

因为你是一个转换的编译器返回一条警告intvoid *可能有不同的尺寸,(但实际上在你的机器,他们具有相同的大小)。

There is a error in you code, when you convert the int to a void* calling the pthead_create function, you should convert it back to an integer type. So, this line is wrong :

您的代码中存在错误,当您将 int 转换为 void* 调用 pthead_create 函数时,您应该将其转换回整数类型。所以,这一行是错误的:

int *id=(int *)s;

it should be :

它应该是 :

int id = (int)s; 

Consider this example where the argument for the thread function is zero.

考虑这个例子,其中线程函数的参数为​​零。

s=0; therefore  ---> *id=(int*)0; // Null pointer 

This is a pointer to the address zero. When you try to deference it, you will likely get an segmentation fault.

这是指向地址零的指针。当您尝试遵从它时,您可能会遇到分段错误。

The best way to do this is by using the intptr_ttype. This type has the same size of a pointer (not int) in every architecture. It is defined as follows :

最好的方法是使用intptr_t类型。这种类型在每个体系结构中都具有相同大小的指针(不是 int)。它的定义如下:

Integer type capable of holding a value converted from a void pointer and then be converted back to that type with a value that compares equal to the original pointer.

整数类型,能够保存从 void 指针转换而来的值,然后使用与原始指针相等的值将其转换回该类型。

So you can do something like this:

所以你可以做这样的事情:

#include <stdint.h>

void *threadfunc(void *param)
{
    int id = (intptr_t) param;
    ...
}

int i, r;
r = pthread_create(&thread, NULL, threadfunc, (void *) (intptr_t) i);

(This example code has been taken from : How to cast an integer to void pointer?)

(此示例代码取自:How to cast an integer to void pointer?

However, there is not guarantee that the size of int is the same of the size of intptr_t, but it's really unlikely that some data is lost in the conversion process.

但是,不能保证 int 的大小与 的大小相同intptr_t,但在转换过程中丢失某些数据的可能性确实不大。

EDIT

编辑

Additional errors :

其他错误:

  • float **Aa, **Bb, **Cc;are not initialised.
  • startand endexceeds the limit of the array. The matrix rows are not allocated in consecutive memory areas.
  • if the thread function is working on a chunks of the matrix, there is not point to go through all the values of the matrix A and B. You might want only the internal loop which, in theory, should work on the part of matrix assigned to it.
  • float **Aa, **Bb, **Cc;未初始化。
  • start并且end超出了数组的限制。矩阵行不在连续的内存区域中分配。
  • 如果线程函数正在处理矩阵的一个块,则没有必要遍历矩阵 A 和 B 的所有值。您可能只需要内部循环,理论上应该在分配的矩阵部分工作到它。

I would consider to rewrite the code for the matrix multiplication because the algorithm is wrong.

我会考虑重写矩阵乘法的代码,因为算法是错误的。

回答by ZeZNiQ

Correct way to achieve this is by referencing the variable "i" (check http://man7.org/linux/man-pages/man3/pthread_create.3.html):

实现这一点的正确方法是引用变量“i”(检查http://man7.org/linux/man-pages/man3/pthread_create.3.html):

pthread_create(&thread_id[i], NULL, prod, (void *)&i);

回答by user3416126

You want to cast integer, short, or char and set a pointer to that value use the reinterpret_cast() call. We used to just (void*) the value and the older compilers were happy, but the new versions, for example g++ 4.8.5, know the value is not the right size for a pointer. reinterpret_cast is just like a cast but it resized it so the compile doesn't complain.

您想要转换 integer、short 或 char 并使用 reinterpret_cast() 调用设置指向该值的指针。我们过去只是 (void*) 值,旧的编译器很高兴,但新版本,例如 g++ 4.8.5,知道该值不是指针的正确大小。reinterpret_cast 就像一个演员,但它调整了它的大小,所以编译不会抱怨。

For example:

例如:

int i = 3;
pointer void * ptr;

ptr = (void*)i;                    // will generate the warning
ptr = reinterpret_cast<void*>(i);  // No warning is generated

X11 example getting a character out of addr and then setting XTPOINTER to it.

X11 示例从 addr 中获取一个字符,然后将 XTPOINTER 设置为它。

val = (XTPOINTER)(*(char*)toVal.addr);                   //  warning
val = reinterpret_cast<XTPOINTER>(*(short*)toVal.addr);  // No warning