将指针传递给main函数后,无法正确打印内容

时间:2014-10-25 21:29:56

标签: c++ pointers function-pointers

我正在练习使用指针来创建对象和访问数据。我创建了一个名为BigNum的stuct来表示一个多位数的数字。当我尝试在readDigits函数中打印结构的内容时,可以很好地打印它。但是,在将指针传递给main函数之后,stuct的内容被打印成随机数。为什么?如何解决?

struct BigNum{
    int numDigits;    //the number of digits
    int *digits;  //the content of the big num
};

int main(){
    BigNum *numPtr = readDigits();
    for (int i=0; i<(numPtr->numDigits);i++ ){
       std::cout << (numPtr->digits)[i] << std::endl;
    }

    return 0;
}

BigNum* readDigits(){
    std::string digits;
    std::cout << "Input a big number:" << std::endl;
    std::cin >> digits; 

    int result[digits.length()];
    toInt(digits,result);

    BigNum *numPtr = new BigNum();
    numPtr->numDigits = digits.length();
    numPtr->digits = result;

/*     When I try to print in here, it's totally okay!

    std::cout << "Here is the content:" << std::endl;
    for (int i=0; i<numPtr->numDigits;i++ ){
    std::cout << (numPtr->digits)[i] << std::endl;
    }
    */

    return numPtr;
}

void toInt(std::string& str, int result[]){
    for (int i=0;i<str.length() ;i++ ){
    result[str.length()-i-1] = (int)(str[i]-'0');
    }
}

3 个答案:

答案 0 :(得分:1)

您有未定义的行为,因为您将自动对象的地址分配给digits指针。当readDigits()返回时,此内存不再有效。您应该为此指针分配基于堆的对象(或某些等效对象,例如使用向量或智能指针):

#include <vector>

struct BigNum{
    int numDigits;            //the number of digits
    std::vector<int> digits;  //the content of the big num
};

然后你可以用这种方式将数字插入向量:

int input;
while ( std::cin >> input) //enter any non-integer to end the loop
{
   digits.push_back(input);
}

答案 1 :(得分:1)

BigNum* readDigits(){
    //....
    int result[digits.length()];
    //....
    numPtr->digits = result;


    return numPtr;
}

result存储在堆栈中。因此,如果您将其作为numPtr的一部分返回,则退出该函数后它将无效。不必将其存储在堆栈中,您必须使用new分配它。

答案 2 :(得分:0)

问题是在函数BigNum* readDigits()中你将apointer分配给堆栈内存到你新分配的BigNum的指针:

int result[digits.length()];   // <--- variable is on the stack!!!
toInt(digits,result);

BigNum *numPtr = new BigNum();
numPtr->numDigits = digits.length();
numPtr->digits = result;   // <--- make pointer to stack memory available to caller of readDigits

现在,如果继续访问numPtr-&gt;数字是正确的,因为结果的内存在堆栈上仍然有效(只要你在readDigits中)。一旦你离开'readDigits()',结果的内存将被覆盖,具体取决于你做什么(调用其他函数,......)。

现在我甚至想知道你为什么不用'int result [digits.length()];'得到编译器错误'因为'digits.length()'不是常数和所需堆栈内存的大小必须在编译时定义...所以我认为结果的大小实际上是0 ... ??测试会是一件好事!

我的建议是修改readDigits的代码,如下所示:

BigNum* readDigits()
{
    std::string digits;
    int i;

    std::cout << "Input a big number:" << std::endl;
    std::cin >> digits; 

    //int result[digits.length()];
    //toInt(digits,result);

    BigNum *numPtr = new BigNum();
    numPtr->numDigits = digits.length();
    numPtr->digits = (int *)malloc(sizeof(int) * numPtr->numDigits);   // allocate heap memory for digits

    toInt(digits, numPtr->digits);

    /*     When I try to print in here, it's totally okay!

    std::cout << "Here is the content:" << std::endl;
    for (i = 0; i  <numPtr->numDigits; i++)
    {
        std::cout << (numPtr->digits)[i] << std::endl;
    }
    */

    return numPtr;
}

如果不再使用'BigNum * numPtr'('free(numPtr-&gt; digits);'),请记住释放你的记忆。否则你会得到内存泄漏(迟早):

int main()
{
    BigNum *numPtr = readDigits();
    int i;

    for (i = 0; i < (numPtr->numDigits); i++)
    {
        std::cout << (numPtr->digits)[i] << std::endl;
    }

    free(numPtr->digits);   // free memory allocated by readDigits(..)
    return 0;
}