为什么即使在函数调用中未进行任何更改,函数也返回两个不同的值?

时间:2019-06-26 17:22:04

标签: c++11

在第一种情况下,代码返回-1

#include <iostream>

template <typename T>
int compare( const T &val1, const T &val2){

    if(val1 < val2) return -1;
    if(val2 < val1) return 1;
    return 0;
}

int main(){

    std::string v1= "hello", v2 = "world";
    std::cout << compare("hello", "world") << std::endl;
}

在第二种情况下,即使方法调用没有变化,代码也返回1。

#include <iostream>

template <typename T>
int compare( const T &val1, const T &val2){

    if(val1 < val2) return -1;
    if(val2 < val1) return 1;
    return 0;
}

int main(){

    std::cout << compare("hello", "world") << std::endl;
}

我正在使用g ++ 7.4.0。

2 个答案:

答案 0 :(得分:1)

在两种情况下,推论Tchar [6]。比较数组时,衰减会指向指向数组第一个元素的指针-char*。因此,您正在比较两个指针,结果是不可预测的,因为您不知道这些字符串文字-“ hello”和“ world”如何位于内存中-地址较低。

您将获得0(这是不可能的,因为作为字符串文字的 hello world 不能占据相同的内存)

if(val1 < val2) return -1;
if(val2 > val1) return 1;    // condition val1 > val2 was not tested
// return 0

一样。 应该是:

if(val1 < val2) return -1;
if(val1 > val2) return 1;

访问godbolt,查看行时生成了什么代码

std::string v1= "hello", v2 = "world";

被评论。

[1]取消注释后的代码为:

.LC0:
        .string "hello"
.LC1:
        .string "world"
main:
        push    rbp
        mov     rbp, rsp
        push    rbx

[2]发表评论

.LC0:
        .string "world"
.LC1:
        .string "hello"
main:
        push    rbp
        mov     rbp, rsp
        mov     esi, OFFSET 

您现在看到了吗? LC0LC1是标签内存(比较了一些值),这就是为什么输出不可预测的原因,它取决于编译器如何在内存中首先存储字符串文字。

答案 1 :(得分:1)

未定义行为,例如使用<之类的操作符指向未指向正常数组元素的指针。不同的字符串文字是不同的数组,并且衰减到指向不同数组元素的指针。任何结果都是可能的。程序可能会打印0,或者崩溃,或者发射核弹头,或者今天做这些事情之一,明天做另一件事。当然,带有UB的两个程序在看似无关的细节上有所不同(例如v1,v2),它们的行为也可能有所不同。没有一个是可以预见的。