← 都来码 / Dolaima← 例程索引c/test/minmax_api.c原文

c/test/minmax_api.c · 2181 字节 · 下载原文

/* minmax_api.c —— `min` / `max` 的**重名消歧**判据。
 * minmax_api.c — criterion for the `min`/`max` de-duplication.
 *
 * ## 为什么单独立一个
 * ## Why a dedicated probe
 *
 * `min` 这个名字在本仓有**三份**定义(`array.c` 收数组 / `math.c` 收两个 int / `builtins.c` 又一份),
 * 而链接器对重名裸标签是**后链的赢、不报错** ⇒ `min(3, 5)` 有可能绑到数组版、
 * 把 `3` 当成**数组指针**去解引用(`arr[0]` 读的是地址 3 处的内存)。
 * 那种错编译期看不出来,运行时要么崩、要么给出一个"看着像个数"的垃圾。
 *
 * `The name `min` had three definitions; the linker silently picks one. If it picks the array
 *  version, `min(3, 5)` dereferences address 3.`
 *
 * 2026-10-08 消歧:数组版统一叫 `*_arr`(`statistics.c` 的 `min_arr`/`max_arr`/`sum_arr`),
 * 两个 int 的版本统一在 `math.c`。本探针钉住的就是"**`min(3,5)` 必须得 3**"。
 *
 * ## 判据
 * ## Criteria
 *
 * 全部是**能分辨"绑错版本"**的取值:数组版拿到 `(3, 5)` 会去读地址 3 处的 `arr[0]`,
 * 结果与 `3` 无关(多半崩或给个垃圾),**不可能**恰好等于 3。
 *
 * 跑法(桌面,秒级):
 *     dotnet scripts/vmlcli/bin/Release/net10.0/vmlcli.dll third_party/vml/Examples/c/test/minmax_api.c
 */

int min(int a, int b);
int max(int a, int b);

int fails = 0;

void ck(char* name, int got, int want) {
    if (got == want) {
        printf("OK   %s = %d\n", name, got);
    } else {
        printf("FAIL %s: got %d, want %d\n", name, got, want);
        fails = fails + 1;
    }
}

int main(void) {
    /* ⚠ 这些取值都"不像指针"(3 / 5 / -7 都不是有效地址),所以一旦绑错版本就会现形 */
    ck("min(3,5)",   min(3, 5),    3);
    ck("max(3,5)",   max(3, 5),    5);
    ck("min(-1,-7)", min(-1, -7), -7);
    ck("max(-1,-7)", max(-1, -7), -1);
    ck("min(0,0)",   min(0, 0),    0);
    ck("max(7,7)",   max(7, 7),    7);

    printf("MINMAX_API %s (fails=%d)\n", fails == 0 ? "PASS" : "FAIL", fails);
    return fails;
}