为什么模板函数中的 strcmp() return 有不同的值?

Why does strcmp() in a template function return a different value?

我正在重读《C++ Primer,第 5 版》。在关于模板的第16章中,有一个“模板非类型参数”的例子:

template<unsigned N, unsigned M>
int compare(const char (&p1)[N], const char (&p2)[M])
{
    return strcmp(p1, p2);
}

int main()
{

    cout << compare("hi", "mom") << endl;
    cout << strcmp("hi", "mom") << endl;


    std::cout << "\ndone!\n";
}

输出:

-5
-1

代码中有什么问题?为什么两者对相同的参数给出不同的值?

这是在 strcmp 传递文字参数时应用的编译器优化,即使在 -O0 上也是如此。请参阅此编译器资源管理器 link:https://godbolt.org/z/T4EKxr

#include <cstring>

template<unsigned N, unsigned M>
int compare(const char (&p1)[N], const char (&p2)[M])
{
    return strcmp(p1, p2);
}

int a() {
    return compare("hi", "mom");
}

int b() {
    return strcmp("hi", "mom");
}

生成的程序集:

.LC0:
        .string "mom"
.LC1:
        .string "hi"
a():
        push    rbp
        mov     rbp, rsp
        mov     esi, OFFSET FLAT:.LC0
        mov     edi, OFFSET FLAT:.LC1
        call    int compare<3u, 4u>(char const (&) [3u], char const (&) [4u])
        pop     rbp
        ret
b():
        push    rbp
        mov     rbp, rsp
        mov     eax, -1
        pop     rbp
        ret
int compare<3u, 4u>(char const (&) [3u], char const (&) [4u]):
        push    rbp
        mov     rbp, rsp
        sub     rsp, 16
        mov     QWORD PTR [rbp-8], rdi
        mov     QWORD PTR [rbp-16], rsi
        mov     rdx, QWORD PTR [rbp-16]
        mov     rax, QWORD PTR [rbp-8]
        mov     rsi, rdx
        mov     rdi, rax
        call    strcmp
        leave
        ret

正如我们所见,对于上面的 b(),gcc 正在将对 strcmp 的调用优化为 -1,而它实际上为 [=] 调用 strcmp 17=]。这是有效的行为,因为 strcmp returns:

Negative value if lhs appears before rhs in lexicographical order.

Zero if lhs and rhs compare equal.

Positive value if lhs appears after rhs in lexicographical order.

-1为负数。

如果我们打开优化,gcc 将同样优化 a()