首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >去引用空指针

问去引用空指针
EN

Stack Overflow用户
提问于 2015-03-15 07:57:25
回答 4查看 872关注 0票数 2

当我看到这类代码时,我正在阅读使用pthreads.h库进行线程编程的指南。不完全是这样,但问题是在void *指针取消引用。

代码语言:javascript
复制
#include <stdio.h>

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

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

为什么我可以用

代码语言:javascript
复制
(int) x

用于在void *中取消func指针

我以为一定是这样的:

代码语言:javascript
复制
* ((int *) x)

关于这行代码在主要功能上的类似问题:

代码语言:javascript
复制
func((void *) x);

我在这里甚至不知道x变量的地址。

EN

回答 4

Stack Overflow用户

回答已采纳

发布于 2015-03-15 07:58:52

在执行x时,没有取消引用(int) x。您只需将指针(或多或少是地址)转换为int,这是一个数字表示形式,可以打印出来。

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

代码语言:javascript
复制
printf("%p\n", x);

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

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

代码语言:javascript
复制
char a = *((char*)x); 

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

票数 10
EN

Stack Overflow用户

发布于 2015-03-15 08:04:31

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

如果希望看到func正在运行,请执行以下操作:

代码语言:javascript
复制
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个内存块,并打印它们的地址。

票数 2
EN

Stack Overflow用户

发布于 2015-03-15 08:06:36

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

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

代码语言:javascript
复制
void *run_thread(void*p) {
   int* pi = p;
   (*pi)++;
   printf("in thread data=%d\n", *pi);
   return pi;
}

一个带有静态数据的线程

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

代码语言:javascript
复制
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个线程,每个线程在这个静态数组中处理自己的元素。

具有堆分配数据的线程

代码语言:javascript
复制
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数据的线程

当然,在线程例程中使用它作为取消引用的指针是没有意义的,这可能是:

代码语言:javascript
复制
 void*run_thread_int(void*p) {
   intptr_t i = (intptr_t)p;
   printf("i=%d\n", i);
   return NULL;
 }

然后你就可以编码

代码语言:javascript
复制
 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 )。

大多数情况下,您将使用一个heap-allocated struct (打包多个值)作为线程函数的参数。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/29058473

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档