Can 似乎使用 return 指向 double 的指针来使用 cout 正确打印值

Can's seems to use return pointer to double for printing value correctly with cout

如果我使用 printf 而不是正确打印值,我无法使用 cout 打印以筛选返回的指向 double 的指针所指向的值,如果我使用指向 double 的指针,我在函数内部声明它也使用 cout正确打印,如果我调试我看到指向 double 的指针及其值正确返回(注意我指向静态而不是本地),无法理解这里的代码有什么问题(在 Visual Studio 2017 社区版中成功编译).

#include "stdafx.h"
#include <iostream>

using namespace std;

const double VAT=0.17;

double * addVAT(static double sum)
{
    sum = sum + (sum*VAT); 
    return &sum;
}


int main()
{
    double total = 120;
    double *totalWithVat;
    cout << "Type the total before VAT:";
    cin >> total;
    totalWithVat = addVAT(total);
    printf("The total with VAT is: %f \n", *totalWithVat);
    cout << *totalWithVat << endl;
}

提前致谢。

您不能将函数参数声明为 static,您还试图将 return 指针指向局部变量,但是当函数离开其范围时,其局部变量将不再存在。如果要在 double:

上获得有效指针,则需要通过引用传递 sum
double * addVAT(double& sum) // takes reference
{
    sum = sum + (sum*VAT); 
    return &sum;
}

但是这个double * addVAT(double& sum)函数会改变传递给它的变量,这里total会在调用方法后改变

int main()
{
    //...
    totalWithVat = addVAT(total);// in addVAT sum will referenced to total from main's scope, so it will return pointer to total

    std::cout << total; // will print the same as totalWithVat
    std::cout << totalWithVat; // will print the same as total, totalWithVat points to total
    //...
}  

如果你不想修改total,那么只需按值和return双值传递它,如下所示:

double addVAT(double sum) 
{
    sum = sum + (sum*VAT); 
    return sum;
}

只需使用常规函数:

double totalWithVAT( double sum )
{
    const double vat = 1.17;
    return sum * vat; 
}

std::cout << "The total with VAT is:" << totalWithVAT( total ) << std::endl;

我们来看看你的addVat功能。

double * addVAT(static double sum)
{
    sum = sum + (sum*VAT); 
    return &sum;
}

您需要从参数列表中删除 static。至少对于 Linux 上的 GCC,这会导致编译错误。当我这样做时,我得到

<source>: In function 'double* addVAT(double)':

<source>:8:24: warning: address of local variable 'sum' returned
 [-Wreturn-local-addr]

double * addVAT(double sum) 
                  ~~~~~~~^~~
Compiler returned: 0

有点符合我的预期。

在您的 main 中,您有 total 作为副本 传递给 addVat,它的名称为 sum.所以在内存中(在运行时堆栈上)你有

主要:总计 main->addVat:sum

addVat 修改 sum 和 return 指向它的指针。问题是在 return 时,addVat 自动释放包含 sum.

的内存

所以现在你有

主要:总计(未更改) main:totalWithVat -> sum 曾经是

的内存

这是未定义的行为。它可能会起作用,但其他一些例程也可能会重新使用和修改 sum 曾经所在的内存。这可能就是您所看到的。 printf 很幸运,得到了 sum 的未修改值,而 cout 得到了修改后的值。

作为您问题的解决方案,有两种可能。您可以只修改一个输入值,像这样

void addVat(double& sum)
{
    sum += sum*VAT;
}

double total = 1.0;
addVat(total);
// total now ~1.17

或者你可以有两个值而不用担心 pointers/references

double addVat(double sum)
{
    return sum + sum*VAT;
}

double total = 1.0;
double totalWithVat = addVat(total);
// totalWithVat now ~1.17

解决方法是从参数中删除 static 并传递指针而不是 static ,奇怪的是旧代码编译并成功地与 printf 一起工作,这是在 cout 和 printf 中都工作的正确代码:

#include "stdafx.h"
#include <iostream>

using namespace std;

const double VAT=0.17;

double * addVAT(double *sum)
{
    *sum = *sum + (*sum*VAT); 
    return sum;
}


int main()
{
    double varTotal = 0;
    double *total;
    total = &varTotal;
    double *totalWithVat;
    cout << "Type the total before VAT:";
    cin >> *total;
    totalWithVat = addVAT(total);
    printf("The total with VAT is: %f \n", *totalWithVat);
    cout << *totalWithVat << endl;
}

只要我不在参数列表中放置静态参数,它就可以正常工作,所以我也可以编写这样的代码:

#include "stdafx.h"
#include <iostream>

using namespace std;

const double VAT = 0.17;

double * addVAT(double sum)
{
    static double sumstatic = sum;
    sumstatic = sumstatic + (sumstatic*VAT);
    return &sumstatic;
}


int main()
{
    double varTotal = 0;
    double total;
    double *totalWithVat;
    cout << "Type the total before VAT:";
    cin >> total;
    totalWithVat = addVAT(total);
    printf("The total with VAT is: %f \n", *totalWithVat);
    cout << "The total with VAT is: " << *totalWithVat << endl;
}