线程返回值

子线程使用​​pthread_exit()​​​向调用线程返回数值,函数原型:​​void pthread_exit(void *retval);​​​
调用线程使用函数​​​pthread_join()​​​的第二个参数​​void **​​​接收返回值。函数原型:​​int pthread_join(pthread_t thread, void **retval);​​​
例子:
main中创建一个线程pthTextCode,在新线程中用pthread_exit()返回一个值,main接收这个值并打出来。

main.c:

void *retval;
//...
retval = NULL;
ret = pthread_create(&pthTextCode,NULL,pthTextCode_run,NULL);
//...
pthread_join(pthTextCode,&retval);
printf("retval from textCode thread: %d\n",*(int*)(retval));
free(retval);
//...

pthTextCode.c

int *retval;
retval = NULL;
//...
retval = (int *)malloc(sizeof(int));
*retval = 1;
pthread_exit((void *)retval);

结果:

main thread wait textCode thread working...
[Switching to Thread 0xb7fe7b70 (LWP 9629)]

Breakpoint 2, pthTextCode_run (arg=0x0) at pthTextCode.c:103
103 retval = (int *)malloc(sizeof(int));
Missing separate debuginfos, use: debuginfo-install glibc-2.12-1.192.el6.i686
(gdb) n
104 *retval = 1;
(gdb) p retval
$1 = (int *) 0xb7400488
(gdb) p &retval
$2 = (int **) 0xb7fe7378
(gdb) c
Continuing.
[Switching to Thread 0xb7fe88d0 (LWP 9626)]

Breakpoint 1, main () at main.c:78
78 pthread_join(pthTextCode,&retval);
(gdb) n
[Thread 0xb7fe7b70 (LWP 9629) exited]
79 printf("retval from textCode thread: %d\n",*(int*)(retval));
Missing separate debuginfos, use: debuginfo-install libgcc-4.4.7-17.el6.i686
(gdb) p retval
$3 = (void *) 0xb7400488
(gdb) p &retval
$4 = (void **) 0xbffff1e4
(gdb) p *retval
Attempt to dereference a generic pointer.
(gdb) n
retval from textCode thread: 1
83

可以看出main中的​​void *reaval​​​和​​pthTextCode​​​中的​​int *retval​​​,两个​​retval​​​都指向同一个地址,即线程​​pthTextCode​​ malloc出来的内存地址。

重复引用头文件

相关错误: ​​/tmp/XXX.o:(.bss+0x0): multiple definition​

通常:

#ifndef  XX_H
#define XX_H
/* ... */
#endif //XX_H

用于防止头文件被重复引用,造成编译效率的低下。但它不能保证头文件里的东西就是唯一的。比如在头文件定义全局变量,这份头文件又被多个c源文件引用,那么编译器就会提示你重复定义。
下面的例子中number.h是这样的:

#ifndef NUMBER_H
#define NUMBER_H

#define LEN 1000010
enum BOOL{False,True};
typedef enum BOOL bool;
bool num_vis[LEN] = {0};
int prime_cnt;
int prime_number[LEN][2];
void get_prime();
#endif //NUMBER_H

test.c、number.c都include了number.h,编译:

[edemon@CentOS tmp]$ gcc test.c number.c -o exe
/tmp/ccJStRc2.o:(.bss+0x0): multiple definition of `num_vis'

当我们将定义改成声明,这个错误就消失了。

// number.h
bool

二进制文件I/O

用fwrite()将2,3,5,7,11写入文件key中,然后通过fread读取。
main.c:

#include "../pthTextRW.h"
//...

int main(){
prime_stack_cnt = 5;
prime_stack[0] = 2;
prime_stack[1] = 3;
prime_stack[2] = 5;
prime_stack[3] = 7;
prime_stack[4] = 11;
prime_write();
prime_read();
return 0;
}

pthTextRW.c中的读写函数:

void prime_write(){
FILE *key_p = NULL;
int i;

key_p = fopen(key_path,"w");
if(key_p == NULL){
perror("key path w fopen: ");
exit(1);
}
for (i=0; i<prime_stack_cnt; i++){
fwrite(&prime_stack[i],sizeof(int),1,key_p);
}
fclose(key_p);
}

void prime_read(){
FILE *key_p;
int i;

key_p = fopen(key_path,"r");
i=0;
if(key_p == NULL){
perror("key_p r fope: ");
exit(1);
}
while(!feof(key_p)){
fread(&prime_stack[i++],sizeof(int),1,key_p);
}
fclose(key_p);

int j;
for (j=0; j<i; j++){
printf("%d ",prime_stack[j]);
}
puts("");
}

用vim打开fwrite生成的二进制文件:

^B^@^@^@^C^@^@^@^E^@^@^@^G^@^@^@^K^@^@^@$

最后一个特殊的字符​​$​​​是行尾锚定:
​​​$ DO 0x24 36 DOLLAR SIGN​​​
表示一行的终结。
其他字符在​​​vim​​​的​​help digraph-table​​能够找到:

                                                      digraph-table
char digraph hex dec official name
^@ NU 0x00 0 NULL (NUL)
^A SH 0x01 1 START OF HEADING (SOH)
^B SX 0x02 2 START OF TEXT (STX)
^C EX 0x03 3 END OF TEXT (ETX)
^D ET 0x04 4 END OF TRANSMISSION (EOT)
^E EQ 0x05 5 ENQUIRY (ENQ)
^F AK 0x06 6 ACKNOWLEDGE (ACK)
^G BL 0x07 7 BELL (BEL)
^H BS 0x08 8 BACKSPACE (BS)
^I HT 0x09 9 CHARACTER TABULATION (HT)
^@ LF 0x0a 10 LINE FEED (LF)
^K VT 0x0b 11 LINE TABULATION (VT)
^L FF 0x0c 12 FORM FEED (FF)
^M CR 0x0d 13 CARRIAGE RETURN (CR)
^N SO 0x0e 14 SHIFT OUT (SO)

vim显示的是字符结果,特殊字符对应的十进制值刚好是​​2, 3, 5, 7, 11​

EOF的值通常设置成-1
​​​feof()​​​返回的是最后一次读操作完毕后的内容,只有多读才能到达EOF。也就是说,上面的​​prime_read()​​​函数读取的内容是多于输入内容的。实践操作后,我发现他总是多读一个0: ​​2 3 5 7 11 0​

工程地址:​​https://github.com/theArcticOcean/CLib/tree/master/myLocker​