C语言最佳实践之库文件介绍(上)

C语言的库文件包括:pthread线程、assert断言、string字符串、time时间、math数学运算、std开头的标准库、sys开头的系统库等。其中,标准库有stdalign.h、stdarg.h、stdatomic.h、stdbool.h、stddef.h、stdint.h、stdio.h、stdlib.h。系统库有sys/mman.h、sys/stat.h、sys/ioctl.h、sys/file.h。详细的库文件如下表所示:
assert.h limits.h stdatomic.h time.h sys/ioctl.h
complex.h locale.h stdbool.h uchar.h sys/file.h
ctype.h math.h stddef.h wchar.h unistd.h
errno.h setjmp.h stdint.h wctype.h pthread.h
fenv.h signal.h stdio.h fcntl.h
float.h stdalign.h stdlib.h sys/mman.h
inttypes.h stdarg.h string.h sys/stat.h

目录

1、assert.h断言

2、ctype.h字符串分类

3、errno.h错误码

4、inttypes.h整数类型

5、limits.h最大值与最小值

6、math.h数学运算

7、setjmp.h长跳转

8、dlfcn.h库操作

9、pthread线程操作

10、Unix标准unistd.h

11、time.h系统时间


1、assert.h断言

assert是c语言库提供的断言,只有一个参数,用于判断结果是否符合预期。示例代码如下:

assert(a > 0);

2、ctype.h字符串分类

ctype用于ASCII字符串分类,用于判断是否为大小写字母、数字、转义字符、转为大写字母、转为小写字母等操作。源码示例如下:

    // 是否为大小写字母或数字
    int isalnum(int __ch);
    // 是否为[A-Za-z]的大小写字母
    int isalpha(int __ch);
    // 是否为空格键或tab键
    int isblank(int __ch);
    // 是否为控制字符
    int iscntrl(int __ch);
    // 是否为数字
    int isdigit(int __ch);
    // 是否为a-z的小写字母
    int islower(int __ch);
    // 是否为标点符号
    int ispunct(int __ch);
    // 是否为转移字符,例如:\f\n\r\t\v
    int isspace(int __ch);
    // 是否为A-Z的大写字母
    int isupper(int __ch);
    // 是否为十六进制0-9A-Fa-f的数字
    int isxdigit(int __ch);
    // 转换为小写字母
    int tolower(int __ch);
    // 转换为大写字母
    int toupper(int __ch);

3、errno.h错误码

errno包含linux/errno.h标准错误码,比如io操作发生错误时,我们可以打印对应的错误信息:

    printf("errno=%d\n", errno);
    printf("err msg=%s\n", strerror(errno));

4、inttypes.h整数类型

inttypes提供整数类型的宏定义,包括:整型、有符号、无符号、八进制、十六进制,位数包括:8位、16位、32位以及64位。源码示例如下:

// 整型int的8位、16位、32位、64位
#define	PRId8			"d"		/* int8_t */
#define	PRId16			"d"		/* int16_t */
#define	PRId32			"d"		/* int32_t */
#define	PRId64			__PRI_64_prefix"d"		/* int64_t */
// 有符号int的8位、16位、32位、64位
#define	PRIi8			"i"		/* int8_t */
#define	PRIi16			"i"		/* int16_t */
#define	PRIi32			"i"		/* int32_t */
#define	PRIi64			__PRI_64_prefix"i"		/* int64_t */
// 无符号int的8位、16位、32位、64位
#define	PRIu8			"u"		/* uint8_t */
#define	PRIu16			"u"		/* uint16_t */
#define	PRIu32			"u"		/* uint32_t */
#define	PRIu64			__PRI_64_prefix"u"		/* uint64_t */
// 十六进制int的8位、16位、32位、64位
#define	PRIx8			"x"		/* uint8_t */
#define	PRIx16			"x"		/* uint16_t */
#define	PRIx32			"x"		/* uint32_t */
#define	PRIx64			__PRI_64_prefix"x"		/* uint64_t */

例如打印输出64位的整型数:

    int64_t num = 1010;
    printf("num=%"PRId64"\n", num);

5、limits.h最大值与最小值

limits提供int、short、char、long类型最大值与最小值的宏定义,包括有符号与无符号。其中无符号最小值等于0,有符号最小值等于最大值相反数加1。源码定义如下:

// 有符号的char、short、int、long最大值
#define SCHAR_MAX __SCHAR_MAX__
#define SHRT_MAX  __SHRT_MAX__
#define INT_MAX   __INT_MAX__
#define LONG_MAX  __LONG_MAX__
// 有符号的char、short、int、long最小值
#define SCHAR_MIN (-__SCHAR_MAX__-1)
#define SHRT_MIN  (-__SHRT_MAX__ -1)
#define INT_MIN   (-__INT_MAX__  -1)
#define LONG_MIN  (-__LONG_MAX__ -1L)
// 无符号的char、short、int、long最大值
#define UCHAR_MAX (__SCHAR_MAX__*2  +1)
#define USHRT_MAX (__SHRT_MAX__ *2  +1)
#define UINT_MAX  (__INT_MAX__  *2U +1U)
#define ULONG_MAX (__LONG_MAX__ *2UL+1UL)
// 无符号的char最大值与最小值
#define CHAR_MIN 0
#define CHAR_MAX UCHAR_MAX
// 64位long long最大值与最小值
#define LLONG_MAX      __LONG_LONG_MAX__
#define LLONG_MIN      (-__LONG_LONG_MAX__-1LL)
#define LONG_LONG_MAX  __LONG_LONG_MAX__
#define LONG_LONG_MIN  (-__LONG_LONG_MAX__-1LL)

6、math.h数学运算

math提供常用的数学运算,包括:正弦/余弦/正切的三角函数、指数函数、对数函数、取绝对值、取模运算、向上取整、向下取整等。源码定义如下:

    // 三角函数:正弦、余弦、正切
    double cos(double __x);
    double sin(double __x);
    double tan(double __x);
    // 反三角函数
    double acos(double __x);
    double asin(double __x);
    double atan(double __x);
    //双曲线三角函数
    double cosh(double __x);
    double sinh(double __x);
    double tanh(double __x);
    // 指数函数
    double exp(double __x);
    // 对数函数
    double log(double __x);
    double log10(double __x);
    // 取绝对值
    double fabs(double __x);
    // x的y次幂
    double pow(double __x, double __y);
    // 开平方根
    double sqrt(double __x);
    // 向上取整
    double ceil(double __x);
    // 向下取整
    double floor(double __x);
    // 四舍五入
    double round(double __x);
    // 取模运算
    double fmod(double __x, double __y);

7、setjmp.h长跳转

setjmp提供长跳转指令功能,与函数内的短跳转goto作用类似。示例代码如下:

#include <setjmp.h>
jmp_buf jump_buf;

void say_hello() {
    longjmp(jump_buf, -1);
}

void hello() {
    if (setjmp(jump_buf) != 0) {
        printf("There is a error!\n");
    }
    say_hello();
}

8、dlfcn.h库操作

dlfcn提供对库文件操作,包括打开库、获取库函数、获取错误信息、关闭库等操作,示例代码如下:

void test_lib() {
    void *ptr = dlopen("libc", RTLD_LAZY);
    if (!ptr)
        return;
    void (*func)() = dlsym(ptr, "printf");
    (*func)("hello,world!\n");
    dlclose(ptr);
}

9、pthread线程操作

pthread是POSIX提供的线程,包括线程、互斥锁和条件变量三个部分。其中,线程有创建、分离、等待、退出等操作,互斥锁有初始化、上锁/解锁、销毁操作,条件变量有初始化、等待、通知、销毁操作。源码定义如下:

    // 创建线程
    int pthread_create(pthread_t* pthread_ptr, pthread_attr_t const* attr, void* (*start_routine)(void*), void*);
    // 分离线程独立运行,不受调用线程控制
    int pthread_detach(pthread_t pthread);
    // 阻塞调用线程,等待本线程执行完成
    int pthread_join(pthread_t pthread, void** return_value_ptr);
    // 退出线程
    void pthread_exit(void* return_value);
    
    // 条件变量初始化
    int pthread_cond_init(pthread_cond_t* cond, const pthread_condattr_t* attr);
    // 条件变量等待
    int pthread_cond_wait(pthread_cond_t* cond, pthread_mutex_t* mutex);
    // 条件变量超时等待
    int pthread_cond_timedwait(pthread_cond_t* cond, pthread_mutex_t* mutex, const struct timespec* timeout);
    // 信号通知
    int pthread_cond_signal(pthread_cond_t* cond);
    // 广播通知
    int pthread_cond_broadcast(pthread_cond_t* cond);
    // 条件变量销毁
    int pthread_cond_destroy(pthread_cond_t* cond);

    // 互斥锁初始化
    int pthread_mutex_init(pthread_mutex_t* mutex, const pthread_mutexattr_t* attr);
    // 互斥锁上锁
    int pthread_mutex_lock(pthread_mutex_t* mutex);
    int pthread_mutex_trylock(pthread_mutex_t* mutex);
    // 互斥锁解锁
    int pthread_mutex_unlock(pthread_mutex_t* mutex);
    // 互斥锁销毁
    int pthread_mutex_destroy(pthread_mutex_t* mutex);

创建线程,并且实现多线程通信,共享变量交替打印从0到100,代码如下:

int num = 0;
int odd_flag = 0;
pthread_cond_t cond;
pthread_mutex_t mutex;

void* odd_task(void *arg)
{ 
    for (int i=0; i<50; i++) {
        pthread_mutex_lock(&mutex);
        while (!odd_flag) {
            pthread_cond_wait(&cond, &mutex);
        }
        printf("odd  = %d\n", num++);
        odd_flag = 0;
        pthread_cond_signal(&cond);
        pthread_mutex_unlock(&mutex);
        sleep(1);
    }
    return NULL;
}

void* even_task(void *arg)
{
    for (int i=0; i<50; i++) {
        pthread_mutex_lock(&mutex);
        while (odd_flag) {
            pthread_cond_wait(&cond, &mutex);
        }
        printf("even = %d\n", num++);
        odd_flag = 1;
        pthread_cond_signal(&cond);
        pthread_mutex_unlock(&mutex);
        sleep(1);
    }
    return NULL;
}

void execute_task() {
    pthread_t work_thread1;
    pthread_t work_thread2;
    pthread_cond_init(&cond, NULL);
    pthread_mutex_init(&mutex, NULL);
    pthread_create(&work_thread1, NULL, even_task, NULL);
    pthread_create(&work_thread2, NULL, odd_task, NULL);
    pthread_join(work_thread1, NULL);
    pthread_join(work_thread2, NULL);
}

10、Unix标准unistd.h

unistd作为Unix标准,提供POSIX操作系统的API,包括fork进程、创建管道、创建软链接、创建硬链接、系统级休眠、IO操作等,源码定义如下:

    // fork进程:pid_t=0为子进程,pid_t=0为父进程
    pid_t  fork(void);
    // 获取进程id
    pid_t  getpid(void);
    // 获取线程id
    pid_t  setsid(void);
    // 退出进程,清理内存
    void _exit(int __status);
    // 改变进程优先级,数值越大优先级越低
    int nice(int __incr);
    // 创建硬链接到当前路径
    int link(const char* __old_path, const char* __new_path);
    // 创建软链接到当前路径
    int symlink(const char* __old_path, const char* __new_path);
    // 修改目录
    int chdir(const char* __path);
    // 移除目录
    int rmdir(const char* __path);
    // 创建管道,fds[0]为管道读取端,fds[1]为管道写入端
    int pipe(int __fds[2]);
    // 修改属组所有权
    int chown(const char* __path, uid_t __owner, gid_t __group);
    // IO的读写、关闭操作
    int close(int __fd);
    ssize_t read(int __fd, void* __buf, size_t __count);
    ssize_t write(int __fd, const void* __buf, size_t __count);
    // 64系统的seek、read、write操作
    off64_t lseek64(int __fd, off64_t __offset, int __whence);
    ssize_t pread64(int __fd, void* __buf, size_t __count, off64_t __offset);
    ssize_t pwrite64(int __fd, const void* __buf, size_t __count, off64_t __offset);
    // 定时器,以秒为单位
    unsigned int alarm(unsigned int __seconds);
    // 休眠,为秒为单位
    unsigned int sleep(unsigned int __seconds);
    // 休眠,以微秒为单位
    int usleep(useconds_t __microseconds);
    // 系统调用
    long syscall(long __number, ...);

11、time.h系统时间

time提供系统级别的时间,有一个tm结构体,包括年月日、时分秒、时区,结构体如下:

struct tm {
  int tm_sec;
  int tm_min;
  int tm_hour;
  int tm_mday;
  int tm_mon;
  int tm_year;
  int tm_wday;
  int tm_yday;
  int tm_isdst;
  long int tm_gmtoff;
  const char* tm_zone;
};

时钟时间的源码函数定义如下:

    // 处理器时钟
    clock_t clock(void);
    // 系统当前时间戳
    time_t time(time_t* __t);
    // 日历时间,返回字符串
    char* ctime(const time_t* __t);
    // 日期时间,转为ascii码
    char* asctime(const struct tm* __tm);
    // 两个时间差值
    double difftime(time_t __lhs, time_t __rhs);
    // tm转为time_t
    time_t mktime(struct tm* __tm);
    // 本地时间
    struct tm* localtime(const time_t* __t);
    // time_t转为tm
    struct tm* gmtime(const time_t* __t);
    // 时间格式化
    char* strptime(const char* __s, const char* __fmt, struct tm* __tm);

时间戳、日历时间、格式化时间,代码示例如下:

    time_t current_time = time(NULL);
    printf("current timestamp=%ld\n", current_time);
    struct tm* tm = localtime(&current_time);
    char *ascii_time = asctime(tm);
    printf("ascii time=%s\n", ascii_time);
    char *calendar_time = ctime(&current_time);
    printf("calendar time=%s\n", calendar_time);
    char timestamp[256];
    strftime(timestamp, 256, "%Y-%m-%d_%H:%M:%S", tm);
    printf("timestamp format=%s\n", timestamp);

打印出来的时间如下:

current timestamp = 1653624175
ascii time        = Fri May 27 12:02:55 2022
calendar time     = Fri May 27 12:02:55 2022
timestamp format  = 2022-05-27_12:02:55

猜你喜欢

转载自blog.csdn.net/u011686167/article/details/124918310