指针错误-即使我认为它已初始化,也“使用未初始化的值”? 旧代码:修改后的代码:编辑数组代码:

问题描述

我正在谈论这段代码

#include <iostream>

using namespace std;

void citire(int& n,int* a)
{
    cin >> n;
    a = new int[100];
    for (int i = 0; i < n; i++)
    {
        cin >> a[i];
    }
}

int main()
{
    int n,*a;
    citire(n,a);
    for (int i = 0; i < n; i++)
    {
        cout << *a << " ";
    }
    return 0;
}

我收到一个错误消息,说a未初始化,我似乎不明白为什么。我在该函数中使用了a = new int[100],并且a一个指针,所以无论在哪里初始化它都无所谓(只要在使用它的值之前就可以了)。

如果我在citire(n,a)中的函数调用int main()之前添加该行,则代码将起作用。

我可能想到的唯一产生错误的原因是函数中发生了初始化。因此,如果我不打电话给citire(n,a),那么a将会被初始化。这是错误的原因吗?

还是我为什么要得到它?

编辑:

之所以出现混乱,是因为我知道数组基本上是指针,并且在将数组作为参数传递时是这样的:

#include <iostream>

using namespace std;

void citire(int& n,int a[])
{
    cin >> n;
    for (int i = 0; i < n; i++)
    {
        cin >> a[i];
    }
}

int main()
{
    int n;
    int a[100];
    citire(n,a);
    for (int i = 0; i < n; i++)
    {
        cout << *a << " ";
    }
    return 0;
}

我不需要通过引用传递它-创建了浅表副本。

为什么认情况下数组会发生这种情况,但指针却不会发生这种情况? (尽管现在很清楚为什么我的程序崩溃了。)

解决方法

我修复了您的代码,并打印了一些地址,供您理解。

旧代码:

#include <iostream>

using namespace std;

void citire(int& n,int* a)
{
    cin >> n;
    a = new int[100];
    for (int i = 0; i < n; i++)
    {
        cin >> a[i];
    }
    cout << "In citire Address of a = " << &a <<endl;
    cout << "In citire Address of n = " << &n <<endl;
}

int main()
{
    int n,*a;
    cout << "Address of a = " << &a <<endl;
    cout << "Address of n = " << &n <<endl;
    citire(n,a);
    for (int i = 0; i < n; i++)
    {
        cout << *a << " ";
    }
    return 0;
}

输出:

Address of a = 0x7ffee5ab6b90
Address of n = 0x7ffee5ab6b98
5
1 2 3 4 5
In citire Address of a = 0x7ffee5ab6b50
In citire Address of n = 0x7ffee5ab6b98
0 0 0 0 0

请注意a中和n函数内部的变量main()citire()的地址。

修改后的代码:

#include <iostream>

using namespace std;

void citire(int &n,int* &a)
{
    cin >> n;
    a = new int[n];
    for (int i = 0; i < n; i++)
    {
        cin >> a[i];
    }
    cout << "In citire Address of a = " << &a <<endl;
    cout << "In citire Address of n = " << &n <<endl;
}

int main()
{
    int n,*a;

    cout << "Address of a = " << &a <<endl;
    cout << "Address of n = " << &n <<endl;

    citire(n,a);

    for (int i = 0; i < n; i++)
    {
        cout << a[i] << " ";
    }

    delete [] a;
    return 0;
}

输出:

Address of a = 0x7ffee0eb1b90
Address of n = 0x7ffee0eb1b98
5
1 2 3 4 5
In citire Address of a = 0x7ffee0eb1b90
In citire Address of n = 0x7ffee0eb1b98
1 2 3 4 5

请注意,在这种情况下,na的地址在函数内部以及在main中都是相同的。由于它们是passed by reference,因此实际变量(只是别名)在存储位置不变的情况下传递,对它们所做的任何更改也将反映在main中。

关键点:除非您强制pointers传递value,否则reference也会传递给函数!

编辑(数组代码):

#include <iostream>

using namespace std;

void citire(int& n,int a[])
{
    cin >> n;
    for (int i = 0; i < n; i++)
    {
        cin >> a[i];
    }
    cout << "In citire Address of a = " << &a <<endl;
    cout << "In citire Address of n = " << &n <<endl;
    cout << "In citire Address of first element of a = " << &a[0] <<endl;
}

int main()
{
    int n;
    int a[100];
    cout << "Address of a = " << &a <<endl;
    cout << "Address of n = " << &n <<endl;
    cout << "Address of first element of a = " << &a[0] <<endl;
    citire(n,a);
    for (int i = 0; i < n; i++)
    {
        cout << a[i] << " ";
    }
    return 0;
}

输出:

Address of a = 0x7ffeef1cda00
Address of n = 0x7ffeef1cd9f8
Address of first element of a = 0x7ffeef1cda00
5
1 2 3 4 5
In citire Address of a = 0x7ffeef1cd9b0
In citire Address of n = 0x7ffeef1cd9f8
In citire Address of first element of a = 0x7ffeef1cda00
1 2 3 4 5

请注意,在array的情况下,即使它们是按值传递的,从某种意义上说,a的地址在函数调用中也会改变,该区域的地址(即100静态声明的整数),基本上数组的第一个元素(&a[0])的地址不变。这样想吧:

  • 您有一个黑匣子,其中存储着一个数字,该数字是a[0]的地址,它是a指向的实际区域。
  • 现在说黑匣子本身有一个标识号XXX
  • 在函数调用期间,您将黑匣子XXX内容放入另一个黑匣子中,例如带有标识号YYY
  • 无法理解YYY具有相同的尖头区域,即&a[0]
  • 您可以将新的YYY黑盒交付使用,该功能使用和操纵以&a[0]开头的区域中的数据。

因此您将结果反映在main()中。另外请注意,arraypointer类型不同

,

我认为您应该进一步了解如何在C函数中传递参数。

首先,尽管a是一个指针,但是它的内存分配发生在citire()中,其中为a分配了新的内存地址。 但是a作为值传递到citire()中。 当程序返回到main()时,您仍具有先前的值a

第二,如果将未初始化的指针传递给函数,则编译器会警告您,因为它假定您将使用指针(e.g. *a = 8),并且由于未初始化,可能导致崩溃。

您最好更改函数原型:

int * cintire(int& n);
void cintire(int& n,int *& a);

Z。