繁体   English   中英

取消引用void指针

[英]Dereferencing void pointer

当我遇到这种代码时,我正在阅读使用pthreads.h库编程的线程指南。 不完全是这样,但事情是在void *指针解除引用。

#include <stdio.h>

void func(void * x) {
    printf("%d\n", (int) x);
}

int main() {
    int x = 10;
    func((void *) x);
    return 0;
}

为什么我可以使用

(int) x

用于在func解除void *指针?

我认为必须是这样的:

* ((int *) x)

关于main函数中这行代码的类似问题:

func((void *) x);

我甚至没有得到x变量的地址。

你没有提领x做时(int) x 您只需将指针(或多或少地址)转换为int ,这是一个数字表示,可以打印。

编辑 :顺便说一句,将x转换为有符号整数( int )应该会给你一个编译器警告。 处理这个问题的恰当的方法是

printf("%p\n", x);

%p是一个特殊的格式说明符,它将传递给printf的东西解释为指针(地址说明符),以十六进制打印,这在处理地址时通常更有用。

EDIT2 :顺便说一句,取消引用x ,你首先必须给它一个有意义的指针类型:

char a = *((char*)x); 

a设置为存储在p包含的地址处的字符。

函数func只打印指针x的地址。

如果要查看func的操作,请执行以下操作:

void func(void * x) {
    printf("%d\n", (int) x);
}

int main() {
    for (int i = 0; i < 5; i++) {
        void *x = malloc(100);
        func(x);
        free(x);
    }
}

此代码将分配5个内存块,并打印其地址。

在实践中,使用pthread_create传递给线程函数的数据应该是静态数据(但是你可以只创建一个使用它的线程,因为它不可重入)或者堆分配的数据,或者转换为其他东西的指针。 如果它是本地数据,它将在启动的线程完成之前被销毁(除非您采取特定的预防措施,例如在调用pthread_join同一函数中调用pthread_create )。

以下是一些示例,假设全局pthread_t thr; 变量和以下线程函数

void *run_thread(void*p) {
   int* pi = p;
   (*pi)++;
   printf("in thread data=%d\n", *pi);
   return pi;
}

一个带有静态数据的线程

回想一下,对于静态数据,您的代码不可重入,并且您只能使用一个线程来使用该数据。

void run_my_thread(void) {
   static int x;
   int err = pthread_create(&thr, NULL, run_thread, &x);
   if (err) 
     { fprintf(stderr, "pthread failed %d (%s)\n", err, strerror(err));
       exit(EXIT_FAILURE);
     }
   do_something_else();
   void* res = NULL;
   pthread_join(thr, &res);
   if (res) printf("got %d from thread\n", *(int*)res);
 }

一个常见的模式可能是拥有一个静态数组,例如5个数据元素,并运行5个线程,每个线程在该静态数组中处理自己的元素。

线程与堆分配数据

void run_my_thread(void) {
   int *pi = malloc(sizeof(int));
   if (!pi) {perror("malloc"); exit(EXIT_FAILURE); };
   *pi = 42;
   int err = pthread_create(&thr, NULL, run_thread, pi);
   if (err) 
     { fprintf(stderr, "pthread failed %d (%s)\n", err, strerror(err));
       exit(EXIT_FAILURE);
     }
   do_something_else();
   void* res = NULL;
   pthread_join(thr, &res);
   if (res) printf("got %d from thread\n", *(int*)res);
   free (pi), pi = NULL;
 }

有时,但这很难看,你可能会将一个inptr_t (不是指向它的指针)传递给pthread_create

线程与intptr_t数据

当然,将它用作线程例程中的解引用指针是没有意义的,它可能是:

 void*run_thread_int(void*p) {
   intptr_t i = (intptr_t)p;
   printf("i=%d\n", i);
   return NULL;
 }

然后你可以编码

 void run_my_thread_int(void) {
    intptr_t j=53;
   int err = pthread_create(&thr, NULL, run_thread_int, (void*)j);
   if (err) 
     { fprintf(stderr, "pthread failed %d (%s)\n", err, strerror(err));
       exit(EXIT_FAILURE);
     }
   do_something_else();
   pthread_join(thr, NULL);
 }

考虑pthread_create一种实用方法是将线程函数看作在机器寄存器中获取单个参数,该寄存器可以保存指针(或者带有上述技巧的intptr_t )。

大多数情况下,您将使用堆分配的 struct (打包几个值) 作为线程函数的参数

当您执行操作时,您没有将指向整数的指针转换为void指针(void *) x - 您正在将整数转换为void指针。 您现在有一个void指针,其指向的地址等于整数x的值。 在函数定义中,您将其反转并将其强制转换为整数。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM