【问题标题】:Why, when I use a pointer to pass an array to a function, the array's length appears to be 1? [duplicate]为什么,当我使用指针将数组传递给函数时,数组的长度似乎为 1? [复制]
【发布时间】:2021-11-20 12:39:47
【问题描述】:

我试图将数组作为指向函数的指针传递,但是当我这样做时,函数只会将指针视为具有 1 个变量的数组。 这是我的代码:

void make3(int* a) {
    int n = sizeof(a) / sizeof(a[0]);
    for (int i = 0; i < n; i++) {a[i] = 3;}
}
int main()
{
    int a[3] = { 0, 1, 2 };
    make3(a);
    int* b = a;
    for (int i = 0; i < sizeof(a)/sizeof(a[0]); i++) {
        cout << *(b + i) << endl;
    }
}

函数 make3 仅将数组的第一个值更改为 3,而不是全部更改。 这是正常的吗? 如果没有,我做错了什么?

【问题讨论】:

  • int a[3] 是一个数组;。 int* a 是一个指针。数组将衰减为指针,但无论如何数组不是指针。你做错了什么是你没有使用std::vector
  • @Eljay 它应该是一个简单的数组,这就是为什么我不能使用向量。不过谢谢!
  • 你能解释一下为什么你特别需要将数组作为指针传递,以及为什么你不能将大小作为参数传递吗?
  • 指针实际上不是数组。在您的示例中,make3() 仅传递main() 传递的数组的第一个元素的地址。该函数在标准 C++ 中无法获取该数组中的元素数。如果您需要获取大小(元素数量),您需要以某种方式传递它(例如作为附加参数),或者正如 Elijay 所说,使用 std::vector (这是一个具有成员函数的数据结构,所以你可以获取大小)。如果你不能使用std::vector,必须传递一个指针,但是你不能以某种方式传递大小,没有办法得到大小。
  • 许多答案和 cmets 建议 std::vector 这是一个很好的替代品。但是对于这些特定的用例(已知的固定大小),还有std::array

标签: c++


【解决方案1】:

当你将一个数组传递给一个函数时,它衰减为一个指针。

int n = sizeof(a) / sizeof(a[0]);

被评估为

int n = sizeof(int*) / sizeof(int);

这是 1(当 sizeof(int*) 是 4 - 取决于实现)。

您应该将数组大小作为参数传递:

void make3(int* a, int n) {
    for (int i = 0; i < n; i++) {a[i] = 3;}
}

int main()
{
    int a[3] = { 0, 1, 2 };
    make3(a, 3);
    for (int i = 0; i < 3; i++) {
        cout << a[i] << endl;
    }
}

如果您无法添加该参数,请使用std::vector

#include <vector>

void make3(std::vector<int> &a) {
    for (int i = 0; i < a.size(); i++) {a[i] = 3;}
}

int main()
{
    std::vector<int> a{ 0, 1, 2 };
    make3(a);
    for (int i = 0; i < a.size(); i++) {
        cout << a[i] << endl;
    }
}

【讨论】:

    【解决方案2】:

    这正常吗?

    是的。

    在 C++ 中,数组会随时衰减为指针。 C++ 从 C 继承了这种便利行为。

    它使人们将数组视为与指针相同。但他们不是。

    在 C++ 中,指针可以指向任何对象 (nullptr),也可以指向对象,或者指向对象数组。指针不知道它是指向一个对象还是一个对象数组。

    (或者是悬空的,或者是未初始化的,或者是一些任意值。应该避免这些。)

    如果不是,我做错了什么?

    你没有使用std::vector

    由于在 cmets 中,您说不能使用 std::vector,那么您需要将数组的长度作为 std::size_t 参数以及指向数组的指针传递。

    但是你也说你不能传入数组的长度。因此,您将需要使用数组引用而不是指针。

    另外,C++17 有std::size(a) 可以用来代替sizeof(a)/sizeof(a[0])

    #include <cstddef>
    #include <iostream>
    
    using std::cout;
    using std::size_t;
    
    template <size_t N>
    void make3(int(&a)[N]) {
        for (size_t i = 0; i < N; ++i) {
            a[i] = 3;
        }
    }
    
    int main() {
        int a[3] = { 0, 1, 2 };
        make3(a);
        int* b = a;
    
        for (size_t i = 0; i < sizeof(a)/sizeof(a[0]); ++i) {
            cout << *(b + i) << "\n";
        }
    }
    

    【讨论】:

    • 更清楚一点:正确初始化的非空指针总是指向一个对象。有时该对象是单个实体,有时它是数组的第一个元素。 (它也可以指向数组中间的一个元素,但这不太常见)。 +1。
    猜你喜欢
    • 1970-01-01
    • 2016-04-22
    • 2015-05-22
    • 1970-01-01
    • 1970-01-01
    • 2015-03-28
    • 2013-02-15
    • 1970-01-01
    相关资源
    最近更新 更多