theArcticOcean

博观而约取,厚积而薄发

【github myLocker】线程返回值,重复引用头文件,二进制文件I/O

线程返回值

子线程使用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        free(buff);

可以看出main中的void *reavalpthTextCode中的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'
/tmp/ccWyM4rc.o:(.bss+0x0): first defined here

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

// number.h
bool num_vis[LEN];

二进制文件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
表示一行的终结。
其他字符在vimhelp 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/myLocker

阅读更多
版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/theArcticOcean/article/details/77151057
文章标签: 线程 二进制 c
想对作者说点什么? 我来说一句

没有更多推荐了,返回首页

加入CSDN,享受更精准的内容推荐,与500万程序员共同成长!
关闭
关闭