C++ 指针上的访问冲突

C++ 指针上的访问冲突,c++,pointers,pass-by-reference,C++,Pointers,Pass By Reference,在这段代码中,我试图将十进制数转换为二进制数。(是的,我知道这样一个函数是存在的——我试着重新发明轮子作为练习。)因为我使用一个函数toBinNum()来转换数字,我想通过引用传递一个空数组,然后在数组中存储我的二进制数字,然后返回到main()函数,我将使用数组binNum。这种情况不会发生;我传递指针,初始化它并存储我的二进制数字,但当我返回main()并尝试访问指针时,它失败,发出“指针访问冲突”错误。我假设内存正在被释放,尽管我不知道为什么,因为指针的作用域在main()中,而new关键

在这段代码中,我试图将十进制数转换为二进制数。(是的,我知道这样一个函数是存在的——我试着重新发明轮子作为练习。)因为我使用一个函数
toBinNum()
来转换数字,我想通过引用传递一个空数组,然后在数组中存储我的二进制数字,然后返回到
main()
函数,我将使用数组
binNum
。这种情况不会发生;我传递指针,初始化它并存储我的二进制数字,但当我返回
main()
并尝试访问指针时,它失败,发出
“指针访问冲突”
错误。我假设内存正在被释放,尽管我不知道为什么,因为指针的作用域在
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;

}
#包括
#包括
使用名称空间std;
无效toBinNum(int,int*,int&);
int main(){
int*binNum=nullptr;//binNum将保存二进制数字数组
int binnumize;
toBinNum(100,binNum,binnumize);
int numOnes=0;
对于(int j=0;j不能通过引用传递指针

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
获得了一个新值。

通过引用传递指针

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
,可用于指定哪些“符号”将插入数组而不是符号“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;
}
您可以使用以下代码生成一个代码,其中位由0和1数值表示:

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

但是缓冲区结果作为以C 0结尾的字符串将不会有用!

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

我使用下面的代码打印整数的二进制转换。在这种代码中,我使用函数
iToBin()
将整数转换为字符数组,可以打印或使用任何字符。此函数还使用可选参数-
sym
,可用于指定哪些“符号”将插入数组而不是符号“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;
}
您可以使用以下代码生成一个代码,其中位由0和1数值表示:

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

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

我很困惑。通过传递int*,我传递的是在
main
中创建的指针,并且只在
toBinNum()中修改它的值
。由于指针存在于main中,为什么在作用域返回到
main
后,它和任何分配给它的
新的
值都不会保留?此外,为什么通过
int*&
将其作为int*的引用会允许以后分配的
新的
内存保留下来?@Alex G,正如我所说的,参数是一个本地v具有块作用域的函数的变量。它获取相应参数值的副本。请参阅我的