Fro*_*Lee 10 c pointers pthreads type-conversion
我想再次选择我的C技能.我想在不同的线程中对一个序列求和,每个线程将返回一个序列的一部分之和的指针.然而,当我试图转换void*类型值local_sum来int,发生了问题.
我试图转换sum += *(int*)local_sum;,发生了一个段错误,我得到了Process finished with exit code 11.
我发现,如果我使用sum += (int)local_sum;,那就没关系.但我无法说服自己:不应该local_sum是一个void *?为什么它可以转换为int用(int)local_sum?
我很感激你能回答这个问题.
将每个进程的返回值相加的部分在这里:
int sum = 0;
for (int i = 0; i < NUM_THREADS; i ++) {
void * local_sum;
pthread_join(count_threads[i], (&local_sum));
sum += (int)local_sum;
}
Run Code Online (Sandbox Code Playgroud)
线程的功能在这里:
void * count_thr(void *arg) {
int terminal = ARRAY_SIZE / NUM_THREADS;
int sum = 0;
for (int i = 0; i < terminal; i ++) {
sum += *((int*)arg + i);
}
return (void*)sum;
}
Run Code Online (Sandbox Code Playgroud)
Fid*_*its 10
您可以通过设置地址来return获得价值.在这种情况下,地址无效.但是,如果你记住这一点,并通过铸造它来获得它的价值将起作用.int sumvoid *sumvoid *int
void *这种方式有时用于return某个值(例如int)或某个地址(例如struct).
为了说明这一点:
int a = 5;
void *p = (void *)a;
int b = (int)p;
Run Code Online (Sandbox Code Playgroud)
a,p和b所有都有价值5. p不指向有效地址.尝试取消引用p会导致未定义的行为:
b = *(int *)p; // Undefined Behavior!
Run Code Online (Sandbox Code Playgroud)
考虑以下程序:
#include <limits.h>
#include <stdio.h>
int main(void)
{
int a, b;
void *p;
a = 5;
p = (void *)a;
b = (int)p;
printf("%d %p %d\n", a, p, b);
a = INT_MAX;
p = (void *)a + 1;
b = (int)p;
printf("%d %p %d\n", a, p, b);
return 0;
}
Run Code Online (Sandbox Code Playgroud)
编译时,我收到以下警告:
$ gcc main.c -o main.exe
main.c: In function ‘main’:
main.c:9:9: warning: cast to pointer from integer of different size [-Wint-to-pointer-cast]
p = (void *)a;
^
main.c:10:9: warning: cast from pointer to integer of different size [-Wpointer-to-int-cast]
b = (int)p;
...
警告发出,因为正如@Gerhardh,指出了sizeof(int)与sizeof(void *)可能是不同的.如果void *超过a int可以容纳的最大值,则可能会丢失数据.
产量
$ ./main.exe 5 0x5 5 2147483647 0x80000000 -2147483648
你不能这样做,*(int*)local_sum因为local_sum不是int*演员void*.local_sum是int演员void*.这是重新解释为地址的数量,但仅用于传输目的,因为pthread_exit只允许你返回void*,而不是int因为标准中明确允许实现定义的转换(6.3.2.3p5,6.3.2.3p6整数和数字之间)只要值适合(如果它们不适合,则UB).如果你返回,例如,0x42地址是不可能的0x42,所以你应该忘记取消引用它,而是你应该尽快将它转换回整数,或者用(int)local_sum;或者更好用(int)(intptr_t)local_sum;(虽然intptr_t不能保证存在)或者(可能是最好的)(int)(intmax_t)local_sum;以避免在LP64平台上转换为不同大小的整数时可能的编译器警告.