代码片段

输出错误信息并退出

#define err_exit(x) do { printf("%s\n", x); exit(1); } while (0)

输出系统错误信息并退出

#define err_sys(x) do { perror(x); exit(1); } while (0)

清空输入缓存

while ((c = getchar()) != '\n' && c != EOF)
    ;
scanf("%*[^\n]");
setbuf(stdin, NULL);

终端屏蔽显示

system("stty -echo");
system("stty echo");

按任意键继续

system("stty raw -echo");
printf("Press any key to continue ...");
getchar();
system("stty -raw echo");

获取文件大小

#include <sys/stat.h>

off_t get_file_size(const char *path)
{
    struct stat sb;

    if (stat(path, &sb) < 0)
        return -1;
    return sb.st_size;
}

指定数组的元素來进行初始化

我们可以指定数组的元素來进行初始化。 这非常有用,特别是当我们需要根据一组 #define 來保持某种映射关系的同步更新时

如下,假设我们想为每个错误码提供一个错误描述的字符串。 为了确保数组保持了最新的定义,无论头文件做了任何修改或增补,我们都可以用这个数组指定的语法

这样就可以静态分配足够的空间,且保证最大的索引是合法的, 同时将特殊的索引初始化为指定的值,并将剩下的索引初始化为 0

#include <stdio.h>

/* Entries may not correspond to actual numbers. Some entries omitted. */
#define EINVAL 1
#define ENOMEM 2
#define EFAULT 3
/* ... */
#define E2BIG  7
#define EBUSY  8
/* ... */
#define ECHILD 12

int main()
{
    char *err_strings[] = {
        [0     ] = "Success",
        [EINVAL] = "Invalid argument",
        [ENOMEM] = "Not enough memory",
        /* ... */
        [E2BIG ] = "Argument list to long",
        [EBUSY ] = "Device or resource busy",
        /* ... */
        [ECHILD] = "No child processe",
    };

    printf("%s\n", err_strings[0]);

    return 0;
}

用结构体与联合体的字段名称來初始化数据

当我们不想将所有字段初始化为 0 时候,这种做法可以很容易的在编译时就生成结构体, 而不需要专门调用一个初始化函数

#include <stdio.h>

struct point {
    int x;
    int y;
    int z;
};

int main()
{
    struct point p = {.x = 3, .y = 4, .z = 5};

    printf("%d\n%d\n%d\n", p.x, p.y, p.z);

    return 0;
}

md5 加密

编译时加上 -lcrypt

#include <stdio.h>
#include <string.h>
#include <crypt.h>

int main()
{
    const char salt[] = "$1$mwumsmsp$";
    char *cp;
    char s[69];

    while (1) {
        scanf("%69s", s);

        cp = crypt(s, salt);
        cp += strlen(salt);

        puts(cp);
    }

    return 0;
}

字符串位操作

/* 将指定位的比特位设为set */
void set_num_bit(char *s, int n, int set)
{
    if (set) {
        *(s + n/8) |= (0x80 >> n%8);
    } else {
        *(s + n/8) &= ~(0x80 >> n%8);
    }
}
/* 取得指定位的比特位 */
int get_num_bit(char *s, int n)
{
    return ((*(s + n/8) << n%8) & 0x80) == 0x80 ? 1 : 0;
}

字符串 + 数字

#include <string.h>
#include <stdio.h>

/* max 999 */
#define TIMES   6

int main(int argc, char *argv[])
{
    /* strlen("input-999") = 9 */
    char path[10] = "input-";
    /* strlen("999") = 3 */
    char number[4];

    for (int i = 1; i <= TIMES; i++) {
        path[6] = '\0';
        sprintf(number, "%d", i);
        printf("%s\n", strncat(path, number, 3));
    }

    return 0;
}

评断字符串是否为数字

#include <string.h>

int is_digit(char *s)
{
    for (int i = 0; i < strlen(s); i++) {
        if (s[i] < '0' || s[i] > '9')
            return FALSE;
    }
    return TRUE;
}

使用二级指针作为矩阵

#include <stdlib.h>
#include <stdio.h>

struct matrix {
    int row;
    int col;
    int **matrix;
};

/*
 * 初始化
 */
void init_matrix(struct matrix *matrix, int row, int col)
{
    matrix->row = row;
    matrix->col = col;

    matrix->matrix = (int **)malloc(sizeof(int *) * row);
    for (int i = 0; i < row; i++) {
        matrix->matrix[i] = (int *)malloc(sizeof(int) * col);
    }
}
/*
 * void init_matrix(int ***p, int row, int col)
 * {
 *     *p = (int **)malloc(sizeof(int *) * row);
 *     for (int i = 0; i < row; i++) {
 *         (*p)[i] = (int *)malloc(sizeof(int) * col);
 *     }
 * }
 *
 * use:
 *     init_matrix(&matrix->matrix, matrix->row, matrix->col);
 */

/*
 * 清理工作
 */
void clear_matrix(struct matrix *matrix)
{
    for (int i = 0; i < matrix->row; i++) {
        free(matrix->matrix[i]);
    }
    free(matrix->matrix);
}

void init_matrix_data(struct matrix *matrix)
{
    for (int i = 0; i < matrix->row; i++) {
        for (int j = 0; j < matrix->col; j++) {
            matrix->matrix[i][j] = i*j;
        }
    }
}

void print_matrix(struct matrix *matrix)
{
    printf("row = %d, col = %d\n", matrix->row, matrix->col);
    for (int i = 0; i < matrix->row; i++) {
        for (int j = 0; j < matrix->col; j++) {
            printf("%d ", matrix->matrix[i][j]);
        }
        printf("\n");
    }
}

int main(int argc, char *argv[])
{
    struct matrix *matrix = (struct matrix *)malloc(sizeof(struct matrix));

    init_matrix(matrix, 5, 2);

    init_matrix_data(matrix);

    print_matrix(matrix);

    clear_matrix(matrix);
    return 0;
}

最大最小

linux-3.17.3/include/linux/kernel.h:

/*
 * min()/max()/clamp() macros that also do
 * strict type-checking.. See the
 * "unnecessary" pointer comparison.
 */
#define min(x, y) ({                \
    typeof(x) _min1 = (x);          \
    typeof(y) _min2 = (y);          \
    (void) (&_min1 == &_min2);      \
    _min1 < _min2 ? _min1 : _min2; })

#define max(x, y) ({                \
    typeof(x) _max1 = (x);          \
    typeof(y) _max2 = (y);          \
    (void) (&_max1 == &_max2);      \
    _max1 > _max2 ? _max1 : _max2; })

#define min3(x, y, z) ({            \
    typeof(x) _min1 = (x);          \
    typeof(y) _min2 = (y);          \
    typeof(z) _min3 = (z);          \
    (void) (&_min1 == &_min2);      \
    (void) (&_min1 == &_min3);      \
    _min1 < _min2 ? (_min1 < _min3 ? _min1 : _min3) : \
        (_min2 < _min3 ? _min2 : _min3); })

#define max3(x, y, z) ({            \
    typeof(x) _max1 = (x);          \
    typeof(y) _max2 = (y);          \
    typeof(z) _max3 = (z);          \
    (void) (&_max1 == &_max2);      \
    (void) (&_max1 == &_max3);      \
    _max1 > _max2 ? (_max1 > _max3 ? _max1 : _max3) : \
        (_max2 > _max3 ? _max2 : _max3); })

typeof 关键词不可用,可试试 __typeof__