Can's, кажется, использует указатель возврата для удвоения для правильного вывода значения cout - PullRequest
0 голосов
/ 03 мая 2018

Я не могу вывести на экран значение, на которое указывает возвращенный указатель, чтобы удвоить его cout, если я использую printf вместо значения print правильно, если я использую указатель для удвоения, который я объявляю внутри функции с cout, он также печатает правильно , если я отлаживаю, я вижу, что указатель на double возвращается правильно с его значением (обратите внимание, что я указываю на статический, а не локальный), я не могу понять, что здесь не так в коде (успешно скомпилировано в выпуске Visual Studio 2017 Community Edition).

#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;
}

Заранее спасибо.

Ответы [ 4 ]

0 голосов
/ 03 мая 2018

Исправлено было удалить статическое из параметра и передать указатель вместо статического, странная вещь, которую старый код скомпилировал и успешно работал с 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;
}
0 голосов
/ 03 мая 2018

Просто используйте обычную функцию:

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

std::cout << "The total with VAT is:" << totalWithVAT( total ) << std::endl;
0 голосов
/ 03 мая 2018

Давайте посмотрим на вашу addVat функцию.

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

Вам необходимо удалить static из списка параметров. По крайней мере, с GCC на Linux это вызывает ошибку компиляции. Когда я это делаю, я получаю

<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: сумма

addVat изменяет sum и возвращает указатель на него. Проблема в том, что по возвращении 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

Или вы можете иметь два значения и не беспокоиться об указателях / ссылках

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

double total = 1.0;
double totalWithVat = addVat(total);
// totalWithVat now ~1.17
0 голосов
/ 03 мая 2018

Вы не можете объявить параметр функции как static, также вы пытаетесь вернуть указатель на локальную переменную, но когда функция выходит из области видимости, ее локальные переменные больше не существуют. Вам нужно передать сумму по ссылке, если вы хотите получить действительный указатель на double:

double * addVAT(double& sum) // takes reference
{
    sum = sum + (sum*VAT); 
    return &sum;
}

Но эта двойная функция * addVAT (double & sum) изменит переданную ей переменную, здесь общая сумма будет изменена после вызова метода

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, просто передайте его по значению и верните двойное значение следующим образом:

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