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

c/test/builtin_dup_api.c · 2907 字节 · 下载原文

/* builtin_dup_api.c —— `builtins.c` 那批"影子副本"统一之后的判据。
 * builtin_dup_api.c — criterion for the unified "shadow copies" in `builtins.c`.
 *
 * ## 背景
 * ## Background
 *
 * `strlen` / `gcd` / `factorial` / `lcm` / `is_prime` / `memcmp` / `memcpy` / `memset` / `sign`
 * 在本仓**各有两份实现**(`builtins.c` 一份、"专名模块"一份),而**两份并不相同**:
 * 有的这边多一层保护、有的那边多一层保护。链接器对重名裸标签**只取一份** ⇒
 * 「哪一份的保护生效」全看链接顺序。
 *
 * 2026-10-08 的处置是**统一**(不是删一份):把两处都写成**较好的那一份**,无论取哪份都一样。
 *
 * ## 判据
 * ## Criteria
 *
 * 挑的是**能分辨"取的是哪一份"**的取值:
 *   · `strlen(0)` —— 只有带空指针保护的那份会返回 0(另一份直接解引用 ⇒ 崩)
 *   · `gcd(-4, 6)` —— 只有带负数处理的那份得 2(另一份得负数)
 *   · `factorial(20)` —— 只有带溢出保护的那份得 0(13! 已超 32 位;另一份给溢出的垃圾)
 *
 * 跑法(桌面,秒级):
 *     dotnet scripts/vmlcli/bin/Release/net10.0/vmlcli.dll third_party/vml/Examples/c/test/builtin_dup_api.c
 */

int strlen(const char* s);
int gcd(int a, int b);
int factorial(int n);
int lcm(int a, int b);
int is_prime(int n);

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) {
    /* ① 空指针保护:只有那一份会返回 0(另一份解引用 0 ⇒ 崩)。
     * ⚠ 实参必须是**运行时才知道**的值 —— 写 `strlen(0)` 会被前端**常量折叠**掉,
     *   于是这一条无论链接到哪一份都是 0(我第一版就是这么写的,反证时它没响)。 */
    char* np = 0;
    np = np + 0;
    ck("strlen(null) 有保护", strlen(np), 0);
    ck("strlen(\"abc\")",  strlen("abc"), 3);

    /* ② 负数处理:`gcd(-4, 6)` 应为 2 */
    int na = 0 - 4;
    int nb = 6;
    ck("gcd(-4,6)", gcd(na, nb), 2);
    ck("gcd(12,18)", gcd(12, 18), 6);

    /* ③ 溢出保护:13! 已超 32 位 ⇒ 返回 0,而不是一个溢出后的垃圾 */
    int big = 20;
    ck("factorial(20) 溢出保护", factorial(big), 0);
    ck("factorial(5)", factorial(5), 120);

    /* ④ lcm:任一为 0 ⇒ 0(不靠 gcd 的返回值去判) */
    ck("lcm(4,6)", lcm(4, 6), 12);
    ck("lcm(0,5)", lcm(0, 5), 0);

    /* ⑤ is_prime */
    ck("is_prime(97)", is_prime(97), 1);
    ck("is_prime(91)", is_prime(91), 0);

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