指针访问冲突

Access violation on pointer

在此代码中,我试图将十进制数转换为二进制数。 (是的,我知道存在这样的函数——我试图重新发明轮子作为练习。)因为我正在使用函数 toBinNum() 来转换数字,所以我想通过引用传递一个空数组,然后将我的二进制数字存储在数组中,并且在 returning 到 main() 函数后,我将得到数组 binNum。这不会发生;我传递指针,初始化它并存储我的二进制数字,但是当我 return 到 main() 并尝试访问指针时,它失败了,发出 "Access violation on pointer" 错误。我假设正在释放内存,尽管我不知道为什么,因为指针的范围在 main() 中,并且 new 关键字用于 toBinNum() 当我在其中创建数组时。为什么这不起作用,我该如何解决?

#include <cmath>
#include <iostream>
using namespace std;

void toBinNum(int, int*, int&);

int main(){
    int* binNum = nullptr; //binNum will hold the array of binary digits
    int binNumSize;
    toBinNum(100, binNum, binNumSize);

    int numOnes = 0;
    for (int j = 0; j < binNumSize; j++){
        if (binNum[j] == 1) //ERROR.
            numOnes++;
        cout << binNum[j];
    }
    cout << numOnes;

    cin.get();
}

/*void toBinNum().
Converts decimal number to binary. 
Parameters: 
    binNum is an int pointer with value NULL, toBinNum() will use this pointer to store an int array of 0s and 1s it generates (each index will hold a binary value).
    binNumSize is an int, holds the length of the binNum array for use in other scopes
    decNum is an int, it is the decimal number that is to be converted to binary.
*/
void toBinNum(int decNum, int* binNum, int& binNumSize) {
    binNumSize = int(log2(decNum)) + 1; //How many digits will binNum be?
    binNum = new int[binNumSize];
    int factor = pow(2, binNumSize - 1); //What is the largest 2^n that we should start dividing decNum by?

    //Find 1s and 0s for binary array
    for (int j = 0; factor >= 1; j++){
        if (decNum / factor > 0){
            binNum[j] = 1; // 1 1 0 0 1
            decNum %= factor; //100   36   4   0
        }
        else
            binNum[j] = 0;
        factor /= 2;  // 64   32    16   8   4   2
    }

    //Output each index of binNum. Confirmation that this function works.
    for (int j = 0; j < binNumSize; j++)
        cout << binNum[j] << endl;

}

通过引用传递指针

void toBinNum(int, int* &, int&);

在 C 中你可以使用另一种间接方式

void toBinNum(int, int**, int*);

你的函数声明的问题在于,任何不是通过引用传递的参数(尽管引用也是函数的局部变量)都是函数的局部变量,在退出函数后被销毁。局部变量的任何更改都不会影响原始参数。

你可以想象函数调用的方式如下。假设您有一个声明为

的函数
void f( int *p );

你可以这样称呼它

int main()
{
    int *q = nullptr;

    f( q );

    //...

那么函数定义可以想象成这样

void f( /* int *p */ )
{
    int *p = q;

    p = new int;

    //...

如您所见,参数 q 未更改。是局部变量p获得了新的值。

我知道这个回复不是问题的正确答案(我已在问题上方的评论中回复),但我认为这是将数字转换为二进制格式的一个很好的解决方案。 然而,它向您展示了在函数调用之外分配资源的想法,而不使用 **&*

我使用下面的代码打印出整数的二进制转换。在这样的代码中,我使用函数 iToBin() 将整数转换为字符数组,可以打印或使用任何你想要的。此函数还使用一个可选参数 - sym - 可用于指定要将哪个 "symbols" 插入数组而不是符号“0”和“1”。函数 iToBin() 将较高位编码为 buff 数组的第一个元素,然后 buff[0] 是转换后数字的较高位。

#include<iostream>
#include<cstdlib>
#include<cmath>
#include<stdint.h>

using namespace std;

char * iToBin(uint64_t n, char *buff, int len, const char *sym=(const char []){'0','1'});

char * iToBin(uint64_t n,char *buff,int len, const char *sym)
{
    uint64_t k=1;
    *(buff+ --len)=0;

    do {
        *(buff+ --len)=(n&k)?sym[1]:sym[0];
        k<<=1;
    } while(k && len);

    return buff;
}

int main(void) {
    uint64_t value;
    int len=0;
    char * buff;

    buff=new char[sizeof(value)*8+1];
    if (buff==NULL) {
       cout << "Not enough memory" << endl;
       return 1;
    }

    do  {
        cout << "Insert the value to convert: ";
        cin >> value;

        //len=(log2(value)+1); //number of digit
        //len++; // to insert the string0 terminator
        //It's better to use this to compute the number of bits!
        len=64;
        while(!(value & (1ULL<<(len-1))) && len>1) len--;
        len++; //to insert string 0 terminator

        iToBin(value,buff,len);

        int numOnes=0;

        for(int i=0;i<len-1;i++) {
            if (buff[i]=='1') {
                numOnes++;
            }
        }

        cout << buff << " contains " << numOnes << " 1" << endl;        

    } while(value!=0);

    delete buff;

    return 0;
}

您也可以使用不同的符号来获得不同的输出,在下面的例子中,您将得到一个输出,其中第 1 个数字为“+”,第 0 个数字为“-”。 (iToBin()可以直接用来打印结果,因为returns是数组指针的值)

    char sym[2];
    sym[0]='-';sym[1]='+';

    cout << iToBin(value,buff,len,sym) << endl;

您可以使用下面的代码生成一个代码,其中的位由 0 和 1 数值表示:

sym[0]=0;sym[1]=1;

但是缓冲区结果不能用作以 C 0 结尾的字符串!