- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我正在做一项作业,要求我使用线程来处理和同步从文件中获取数据。我的教授告诉我,我可以将数据更改为空指针,将其传递给我的函数,然后将其转换回来。我正在尝试使用文件 IO 来做到这一点。
pthread_create(&th1, NULL, processing, (void *)&fp);
在我的处理函数中,我尝试将其转换回 FILE 指针:
FILE driveOne = (FILE *)file;
这显然行不通,所以有人可以向我解释一下吗?
最佳答案
这是一个更完整的示例。
假设您的工作函数需要一个文件句柄。为了简单起见,假设它从中读取每个字符,并返回读取的字符数,转换为指针:
void *worker(void *data)
{
FILE *handle = (FILE *)data;
uintptr_t count = 0;
if (handle && !ferror(handle)) {
/* handle is a valid file handle */
while (getc(handle) != EOF)
count++;
}
return (void *)count;
}
如果count
属于 intptr_t
之外的其他类型或uintptr_t
(在 <stdint.h>
中声明,通常通过包含 <inttypes.h>
来包含),您需要首先将其转换为该类型,然后转换为 void 指针,即 (void *)(uintptr_t)count
.
因为这样的工作线程不需要太多堆栈(准确地说,几乎不需要),并且默认线程堆栈大小很大(兆字节),所以我们可以节省一些内存(如果需要,可以允许更多线程,特别是在 32位架构)通过创建一个 pthread 属性来指示 pthread_create()
使用较小的堆栈。该属性不会被调用“消耗”;它更像是一个配置 block 。
假设您有三个流,FILE *in[3];
,并且您希望使用三个线程来检查它们的长度。使用 pthread 属性来使用较小的堆栈( 2*PTHREAD_STACK_MIN
,如 <limits.h>
中定义,对于不使用 alloca()
或本地数组的工作线程来说是一个良好、安全的值。):
pthread_t worker_id[3];
uintptr_t length[3];
pthread_attr_t attrs;
void *retptr;
int i, result;
/* Create a pthread attribute set, defining smaller stack size. */
pthread_attr_init(&attrs);
pthread_attr_setstacksize(&attrs, 2*PTHREAD_STACK_MIN);
/* Create the three worker threads. */
for (i = 0; i < 3; i++) {
result = pthread_create(&(worker_id[i]), &attrs, worker, (void *)in[i]);
if (result) {
fprintf(stderr, "Cannot create thread: %s.\n", strerror(result));
exit(EXIT_FAILURE);
}
}
/* pthread attributes are no longer needed. */
pthread_attr_destroy(&attrs);
/*
... This thread can do something else here ...
*/
/* Reap the threads, and collect their return values. */
for (i = 0; i < 3; i++) {
result = pthread_join(worker_id[i], &retptr);
if (result) {
fprintf(stderr, "Cannot reap thread: %s.\n", strerror(result));
exit(EXIT_FAILURE);
}
length[i] = (uintptr_t)retptr;
}
for (i = 0; i < 3; i++)
printf("in[%d] contained %llu chars.\n", i, (unsigned long long)length[i]);
<小时/>
当您想要将多个参数传递给线程函数时,可以使用相同的模式。您首先构建一个结构来保存这些参数,然后创建它们。您可以动态分配它们,将它们声明为全局变量,或者在 main() 中将它们声明为局部变量——当工作线程存在时,任何在整个持续时间内存在的作用域都可以工作。
例如,假设您的工作函数计算每个 unsigned char
的直方图从流中读取的值:
struct work {
pthread_t id; /* Thread identifier */
FILE *in; /* File handle to read from */
size_t count[UCHAR_MAX + 1]; /* Histogram */
};
void *worker(void *data) {
struct work *const work = (struct worker_data *)data;
int c;
if (!work || !work->in) {
/* Invalid data, or invalid file handle. */
return (void *)(intptr_t)(EINVAL);
}
if (ferror(work->in)) {
/* Stream is in error state. */
return (void *)(intptr_t)(EIO);
}
/* Read the stream. */
while ((c = getc(work->in)) != EOF) {
/* Update histogram. */
work->count[(unsigned char)c]++;
}
/* Did the reading stop due to an I/O error? */
if (ferror(work->in))
return (void *)(intptr_t)(EIO);
/* No errors, all done. */
return (void *)0;
}
请注意struct work *const work = ...
初始化常量指针work
,不是指向常量的指针。 const
只是有一个优化告诉 C 编译器我们不会尝试修改 work
指针本身。它指向的数据是可以修改的。
(要读取指针声明,请从右向左读取它们,将每个 *
替换为“是指向”的指针,以获得正确的含义。)
创建这些工作人员的代码非常相似,只是我们动态分配工作:
struct work *work[3];
pthread_attr_t attrs;
void *retptr;
int i, result;
/* Create and initialize the three pointers. */
for (i = 0; i < 3; i++) {
/* Allocate a work structure. */
work[i] = malloc(sizeof *(work[i]));
if (!work[i]) {
fprintf(stderr, "Out of memory.\n");
exit(EXIT_FAILURE);
}
/* Copy the handle to read from, */
work[i]->in = in[i];
/* and clear the histogram part. */
memset(work[i]->count, 0, sizeof work[i]->count);
}
/* Create a pthread attribute set, defining smaller stack size. */
pthread_attr_init(&attrs);
pthread_attr_setstacksize(&attrs, 2*PTHREAD_STACK_MIN);
/* Create the three worker threads. */
for (i = 0; i < 3; i++) {
result = pthread_create(&(work[i]->id), &attrs, worker, (void *)work[i]);
if (result) {
fprintf(stderr, "Cannot create thread: %s.\n", strerror(result));
exit(EXIT_FAILURE);
}
}
/* pthread attributes are no longer needed. */
pthread_attr_destroy(&attrs);
/*
... This thread can do something else here ...
*/
/* Reap the threads, and collect their return values. */
for (i = 0; i < 3; i++) {
result = pthread_join(work[i]->id, &retptr);
if (result) {
fprintf(stderr, "Cannot reap thread: %s.\n", strerror(result));
exit(EXIT_FAILURE);
}
/* If the thread reported a failure, print the corresponding
error message (but do not exit). */
if (retptr)
fprintf(stderr, "Thread %d of 3: %s.\n", i+1, strerror((intptr_t)retptr));
/* ... print the histogram here? ... */
}
/* Free the work structures. */
for (i = 0; i < 3; i++)
free(work[i]);
如果您不想在发生错误时中止程序,请注意free(NULL)
。是安全的,什么也不做;那struct work *pointerarray[SIZE] = {0};
声明一个指向 struct work
的 SIZE 指针数组,并将它们全部初始化为零。例如,如果分配或线程创建在某个时刻失败,您可以只 free()
每个指针,无论其分配是否成功。
也就是说,如果您想分配三种不同类型的结构( struct atype *a;
、 struct btype *b;
和 struct ctype *c;
),您可以这样做
a = malloc(sizeof *a);
b = malloc(sizeof *b);
c = malloc(sizeof *c);
if (!a || !b || !c) {
free(c);
free(b);
free(a);
return ALLOCATION_FAILED;
}
/* Allocation was successful */
而不是分配每一个并单独测试失败。
关于c - pthread 空指针转换,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52824232/
我刚接触 C 语言几周,所以对它还很陌生。 我见过这样的事情 * (variable-name) = -* (variable-name) 在讲义中,但它到底会做什么?它会否定所指向的值吗? 最佳答案
我有一个指向内存地址的void 指针。然后,我做 int 指针 = void 指针 float 指针 = void 指针 然后,取消引用它们以获取值。 { int x = 25; vo
我正在与计算机控制的泵进行一些串行端口通信,我用来通信的 createfile 函数需要将 com 端口名称解析为 wchar_t 指针。 我也在使用 QT 创建一个表单并获取 com 端口名称作为
#include "stdio.h" #include "malloc.h" int main() { char*x=(char*)malloc(1024); *(x+2)=3; --
#include #include main() { int an_int; void *void_pointer = &an_int; double *double_ptr = void
对于每个时间步长,我都有一个二维矩阵 a[ix][iz],ix 从 0 到 nx-1 和 iz 从 0 到 nz-1。 为了组装所有时间步长的矩阵,我定义了一个长度为 nx*nz*nt 的 3D 指针
我有一个函数,它接受一个指向 char ** 的指针并用字符串填充它(我猜是一个字符串数组)。 *list_of_strings* 在函数内部分配内存。 char * *list_of_strings
我试图了解当涉及到字符和字符串时,内存分配是如何工作的。 我知道声明的数组的名称就像指向数组第一个元素的指针,但该数组将驻留在内存的堆栈中。 另一方面,当我们想要使用内存堆时,我们使用 malloc,
我有一个 C 语言的 .DLL 文件。该 DLL 中所有函数所需的主要结构具有以下形式。 typedef struct { char *snsAccessID; char *
指针, C语言的精髓 莫队先咕几天, 容我先讲完树剖 (因为后面树上的东西好多都要用树剖求 LCA). 什么是指针 保存变量地址的变量叫做指针. 这是大概的定义, 但是Defad认为
我得到了以下数组: let arr = [ { children: [ { children: [], current: tru
#include int main(void) { int i; int *ptr = (int *) malloc(5 * sizeof(int)); for (i=0;
我正在编写一个程序,它接受一个三位数整数并将其分成两个整数。 224 将变为 220 和 4。 114 将变为 110 和 4。 基本上,您可以使用模数来完成。我写了我认为应该工作的东西,编译器一直说
好吧,我对 C++ 很陌生,我确定这个问题已经在某个地方得到了回答,而且也很简单,但我似乎找不到答案.... 我有一个自定义数组类,我将其用作练习来尝试了解其工作原理,其定义如下: 标题: class
1) this 指针与其他指针有何不同?据我了解,指针指向堆中的内存。如果有指向它们的指针,这是否意味着对象总是在堆中构造? 2)我们可以在 move 构造函数或 move 赋值中窃取this指针吗?
这个问题在这里已经有了答案: 关闭 11 年前。 Possible Duplicate: C : pointer to struct in the struct definition 在我的初学者类
我有两个指向指针的结构指针 typedef struct Square { ... ... }Square; Square **s1; //Representing 2D array of say,
变量在内存中是如何定位的?我有这个代码 int w=1; int x=1; int y=1; int z=1; int main(int argc, char** argv) { printf
#include #include main() { char *q[]={"black","white","red"}; printf("%s",*q+3); getch()
我在“C”类中有以下函数 class C { template void Func1(int x); template void Func2(int x); }; template void
我是一名优秀的程序员,十分优秀!