# ===== CodeLab: c-multifile =====
# 以下代码片段按文章出现顺序拼接, 共 8 段

# ----- 片段 1 (c) -----
/* 声明:只告诉编译器"存在这样一个函数" */
int add(int a, int b);

/* 定义:写出真正的函数体 */
int add(int a, int b) {
    return a + b;
}

/* 全局变量的声明与定义 */
extern int counter;   /* 声明:变量在别的 .c 里定义 */
int counter = 0;      /* 定义:真正分配内存 */

# ----- 片段 2 (c) -----
#ifndef CALC_H
#define CALC_H

/* 加减乘除;出错时返回 0 并设置 errno */
int add(int a, int b);
int sub(int a, int b);
int mul(int a, int b);
int divide(int a, int b);

#endif /* CALC_H */

# ----- 片段 3 (c) -----
#include "calc.h"
#include <errno.h>
#include <limits.h>

int add(int a, int b) {
    if ((b > 0 && a > INT_MAX - b) ||
        (b < 0 && a < INT_MIN - b)) {
        errno = ERANGE;   /* 溢出 */
        return 0;
    }
    return a + b;
}

int sub(int a, int b) {
    if ((b < 0 && a > INT_MAX + b) ||
        (b > 0 && a < INT_MIN + b)) {
        errno = ERANGE;
        return 0;
    }
    return a - b;
}

int mul(int a, int b) {
    if (a != 0 && b != 0 &&
        (a > INT_MAX / b || a < INT_MIN / b)) {
        errno = ERANGE;
        return 0;
    }
    return a * b;
}

int divide(int a, int b) {
    if (b == 0) {
        errno = EDOM;     /* 除零 */
        return 0;
    }
    return a / b;
}

# ----- 片段 4 (c) -----
#include <stdio.h>
#include "calc.h"

int main(void) {
    printf("3 + 4 = %d\n", add(3, 4));
    printf("10 - 7 = %d\n", sub(10, 7));
    printf("6 * 7 = %d\n", mul(6, 7));
    printf("8 / 2 = %d\n", divide(8, 2));
    printf("1 / 0 = %d\n", divide(1, 0));   /* 除零:返回 0 */
    return 0;
}

# ----- 片段 5 (bash) -----
# 第一步:分别编译(加 -c 只编译不链接)
gcc -Wall -Wextra -c calc.c -o calc.o
gcc -Wall -Wextra -c main.c -o main.o

# 第二步:链接成可执行文件
gcc calc.o main.o -o app
./app

# ----- 片段 6 (bash) -----
gcc -Wall -Wextra calc.c main.c -o app

# ----- 片段 7 (text) -----
CC = gcc
CFLAGS = -Wall -Wextra

app: main.o calc.o
	$(CC) main.o calc.o -o app

main.o: main.c calc.h
	$(CC) $(CFLAGS) -c main.c

calc.o: calc.c calc.h
	$(CC) $(CFLAGS) -c calc.c

clean:
	rm -f *.o app

# ----- 片段 8 (bash) -----
ar rcs libcalc.a calc.o
gcc main.c -L. -lcalc -o app
./app
