如何通过函数的 void 指针参数传递一个 int 值并将其转换回 int 值?
How do you pass an int value through a void pointer paramater of a function and convert it back to an int value?
我正在尝试创建一个多线程程序,为每个接收它的文件创建一个线程(file1.txt 到 file20.txt),我需要将一个变量传递给函数使用 pthread_create
。我很难将我的 int 值传递给函数,因为 pthread_create
只接受 void*
所以我的函数必须接受 void*
.
我对指针有一些经验,但我不太了解 void 指针的概念。据我所知,我的 pthread_create
应该看起来与 pthread_create(&tids[i], NULL, getSales, (void*)i );
相似
在 main() 中:
using namespace std;
int main(int argc, char **argv){
int numfiles = 20;
// Thread_ID's
pthread_t tids[numfiles];
// create threads
for(int i = 1; i <= numfiles; i++){
pthread_create(&tids[i], NULL, getSales, (void*)i );
}
// wait until threads are done
//join threads together so they run simultaneously
for(int i = 1; i <= numfiles; i++){
pthread_join(tids[i], NULL);
}
}
目前在 getSales 中:
void* getSales(void* fileNum){
int* num = (int*)fileNum;
cout << &num <<endl;
pthread_exit(0);
}
目前,当我编译这段代码时,它崩溃了,并给了我多行回溯,但似乎错误只是 getSales 函数,目前输出应该以随机顺序打印数字 1 到 20,因为该函数是 multi -线程。
gcc staplemax.cpp -lpthread -o staplemax
staplemax.cpp: In function ‘int main(int, char**)’:
staplemax.cpp:114:57: warning: cast to pointer from integer of different size [-Wint-to-pointer-cast]
pthread_create(&tids[i], NULL, getSales, (void*)i );
^
/tmp/ccf6zgpk.o: In function `getSales(void*)':
staplemax.cpp:(.text+0x10e): undefined reference to `std::cout'
staplemax.cpp:(.text+0x113): undefined reference to `std::ostream::operator<<(void const*)'
staplemax.cpp:(.text+0x118): undefined reference to `std::basic_ostream<char, std::char_traits<char> >& std::endl<char, std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&)'
编辑:
我现在使用 g++ staplemax.cpp -lpthread -o staplemax
而不是推荐的 gcc staplemax.cpp -lpthread -o staplemax
进行编译。
我也更改了 main,因为有人指出 &i
可能随着 for 循环的每个循环的调用而更改。我的代码目前看起来像这样
void* getSales(void* fileNum){
int num = *(int*)fileNum;
cout << num <<endl;
pthread_exit(0);
}
int main(int argc, char **argv){
int numfiles = 20;
// Thread_ID
pthread_t tids[numfiles];
int args[numfiles];
// create thread
for(int i = 0; i < numfiles; i++){
args[i] = i+1;
pthread_create(&tids[i], NULL, getSales, &args[i] );
}
// wait until thread is done //join
for(int i = 0; i < numfiles; i++){
pthread_join(tids[i], NULL);
}
}
这可以编译(使用 g++
)但并非所有数字都是 1-20
3
2
9
1
10
6
87
5
4
11
12
13
14
15
16
17
18
19
20
您将 int
投射到 void*
。要撤消它,请将 void*
转换回 int
。所以:
int* num = (int*)fileNum;
应该是:
int num = (int)fileNum;
对此的经典解决方案是使用一个对象数组来表示每个 pthread 的参数。也就是说,每个线程都有一个关联的唯一位置来保存它的参数。您只需要传递一个指向该唯一位置的指针。
这是一个例子:
void *pthread_func(void *_arg) {
int arg = *(int*)_arg; // we're receiving an int
// ...
}
int main() {
pthread_t threads[20];
int args[20]; // unique arg location for each thread
for (int i = 0; i < 20; ++i) {
args[i] = (whatever you want to pass)
// create the thread, give it its unique arg location
pthread_create(&threads[i], NULL, pthread_func, &args[i]);
}
// ... join the threads, etc. ...
}
通过地址(即 &i
)传递循环变量的问题是它可能(肯定会)在每个线程完成之前被更改。
例如,在迭代 i=0
中,您传递了 &i
。除非你立即加入 newly-created 线程,否则下一个循环迭代会将 i
更改为 1,这肯定会弄乱你刚刚创建的线程。更糟糕的是,i=0
线程可能永远不会看到 0,因为线程创建可能会延迟,具体取决于系统正在做什么。由于它们都指向相同的位置,因此它们都观察到相同的值(除了迂腐的内存排序考虑因素)。
编辑:
因为您使用的线程数将(应该)总是很小(因为您创建的 运行ning 线程永远不应超过处理器 运行 它们的数量),内存开销上面的方法很小。但是,如果您传递的是整数类型,并且希望尽可能多地保存 space,则可以将其转换为 void*
(因为指针也是整数类型)。
唯一需要注意的是,只有当整数类型和指针具有相同的位数时,才允许在它们之间进行转换。为此,请使用 intptr_t
或 uintptr_t
作为中介。
这是一个例子:
void *pthread_func(void *_arg) {
int arg = (int)(intptr_t)_arg; // we're receiving an int encoded as void*
// ...
}
int main() {
pthread_t threads[20];
for (int i = 0; i < 20; ++i) {
void *arg = (void*)(intptr_t)(whatever you want to pass);
// create the thread, give it its packed argument
pthread_create(&threads[i], NULL, pthread_func, arg);
}
// ... join the threads, etc. ...
}
我正在尝试创建一个多线程程序,为每个接收它的文件创建一个线程(file1.txt 到 file20.txt),我需要将一个变量传递给函数使用 pthread_create
。我很难将我的 int 值传递给函数,因为 pthread_create
只接受 void*
所以我的函数必须接受 void*
.
我对指针有一些经验,但我不太了解 void 指针的概念。据我所知,我的 pthread_create
应该看起来与 pthread_create(&tids[i], NULL, getSales, (void*)i );
在 main() 中:
using namespace std;
int main(int argc, char **argv){
int numfiles = 20;
// Thread_ID's
pthread_t tids[numfiles];
// create threads
for(int i = 1; i <= numfiles; i++){
pthread_create(&tids[i], NULL, getSales, (void*)i );
}
// wait until threads are done
//join threads together so they run simultaneously
for(int i = 1; i <= numfiles; i++){
pthread_join(tids[i], NULL);
}
}
目前在 getSales 中:
void* getSales(void* fileNum){
int* num = (int*)fileNum;
cout << &num <<endl;
pthread_exit(0);
}
目前,当我编译这段代码时,它崩溃了,并给了我多行回溯,但似乎错误只是 getSales 函数,目前输出应该以随机顺序打印数字 1 到 20,因为该函数是 multi -线程。
gcc staplemax.cpp -lpthread -o staplemax
staplemax.cpp: In function ‘int main(int, char**)’:
staplemax.cpp:114:57: warning: cast to pointer from integer of different size [-Wint-to-pointer-cast]
pthread_create(&tids[i], NULL, getSales, (void*)i );
^
/tmp/ccf6zgpk.o: In function `getSales(void*)':
staplemax.cpp:(.text+0x10e): undefined reference to `std::cout'
staplemax.cpp:(.text+0x113): undefined reference to `std::ostream::operator<<(void const*)'
staplemax.cpp:(.text+0x118): undefined reference to `std::basic_ostream<char, std::char_traits<char> >& std::endl<char, std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&)'
编辑:
我现在使用 g++ staplemax.cpp -lpthread -o staplemax
而不是推荐的 gcc staplemax.cpp -lpthread -o staplemax
进行编译。
我也更改了 main,因为有人指出 &i
可能随着 for 循环的每个循环的调用而更改。我的代码目前看起来像这样
void* getSales(void* fileNum){
int num = *(int*)fileNum;
cout << num <<endl;
pthread_exit(0);
}
int main(int argc, char **argv){
int numfiles = 20;
// Thread_ID
pthread_t tids[numfiles];
int args[numfiles];
// create thread
for(int i = 0; i < numfiles; i++){
args[i] = i+1;
pthread_create(&tids[i], NULL, getSales, &args[i] );
}
// wait until thread is done //join
for(int i = 0; i < numfiles; i++){
pthread_join(tids[i], NULL);
}
}
这可以编译(使用 g++
)但并非所有数字都是 1-20
3
2
9
1
10
6
87
5
4
11
12
13
14
15
16
17
18
19
20
您将 int
投射到 void*
。要撤消它,请将 void*
转换回 int
。所以:
int* num = (int*)fileNum;
应该是:
int num = (int)fileNum;
对此的经典解决方案是使用一个对象数组来表示每个 pthread 的参数。也就是说,每个线程都有一个关联的唯一位置来保存它的参数。您只需要传递一个指向该唯一位置的指针。
这是一个例子:
void *pthread_func(void *_arg) {
int arg = *(int*)_arg; // we're receiving an int
// ...
}
int main() {
pthread_t threads[20];
int args[20]; // unique arg location for each thread
for (int i = 0; i < 20; ++i) {
args[i] = (whatever you want to pass)
// create the thread, give it its unique arg location
pthread_create(&threads[i], NULL, pthread_func, &args[i]);
}
// ... join the threads, etc. ...
}
通过地址(即 &i
)传递循环变量的问题是它可能(肯定会)在每个线程完成之前被更改。
例如,在迭代 i=0
中,您传递了 &i
。除非你立即加入 newly-created 线程,否则下一个循环迭代会将 i
更改为 1,这肯定会弄乱你刚刚创建的线程。更糟糕的是,i=0
线程可能永远不会看到 0,因为线程创建可能会延迟,具体取决于系统正在做什么。由于它们都指向相同的位置,因此它们都观察到相同的值(除了迂腐的内存排序考虑因素)。
编辑:
因为您使用的线程数将(应该)总是很小(因为您创建的 运行ning 线程永远不应超过处理器 运行 它们的数量),内存开销上面的方法很小。但是,如果您传递的是整数类型,并且希望尽可能多地保存 space,则可以将其转换为 void*
(因为指针也是整数类型)。
唯一需要注意的是,只有当整数类型和指针具有相同的位数时,才允许在它们之间进行转换。为此,请使用 intptr_t
或 uintptr_t
作为中介。
这是一个例子:
void *pthread_func(void *_arg) {
int arg = (int)(intptr_t)_arg; // we're receiving an int encoded as void*
// ...
}
int main() {
pthread_t threads[20];
for (int i = 0; i < 20; ++i) {
void *arg = (void*)(intptr_t)(whatever you want to pass);
// create the thread, give it its packed argument
pthread_create(&threads[i], NULL, pthread_func, arg);
}
// ... join the threads, etc. ...
}