将struct数组分配给指针

时间:2011-01-30 12:40:18

标签: c arrays pointers struct

我初始化了一个结构数组(只包含一个名为name的char字符串。然后将这个结构数组分配给一个指针,如下所示:

location locations[2] = {{"Padstow", 50.5384, -4.9378}, 
                         {"Newquay", 50.412, -5.0757}};

int location_size = 2;

location *loc_ptr;
loc_ptr = &locations[0];

// pick an element to remove
location element = loc_ptr[1];

remove_element(loc_ptr, location_size, element);

然后我将这个指针传递给一个函数。在这个函数里面,我删除了一个数组元素。这是通过迭代当前数组并创建一个新数组来完成的。新数组包含我期望的数据。

remove_element函数内:

void remove_element(location *ptr, int count, location element) {

    // create the new array
    location new_locations[count-1];

    // go through and pick out the non-matching element

    // create the new pointer        
    location *new_ptr;
    new_ptr = &new_locations[0];

    // assign the new array to the original pointer
    ptr = new_ptr;
}    

但是,它并没有改变原始数据。你能解释一下我把这个新数组分配给原始指针的错误吗?

6 个答案:

答案 0 :(得分:2)

我在C中已经做了很长时间了,所以我有点生疏,但我会试一试......

我会看到(至少)有两种方法可以使它工作:从函数返回新数组的新指针并将其存储在旧指针中,类似于(这可能在语法上不正确):

loc_ptr = someFunctionCreatingTheNewArrayAndReturningAPointerToIt(loc_ptr);

另一种可能性是将loc_ptr传递给函数by-pointer而不是by-value。基本上,您将把“指针指针”作为参数传递给函数,指向指向loc_ptr的指针指针。在函数内部,您可以从指向指针的指针取消引用数组memoryaddress以访问原始数组。一旦创建并填充了新数组,就将新数组的内存地址放入由指针传递的参数中。

编辑:我提出了两种方式的快速示例,这实际上是在C ++中,但我99%肯定,指针在C中的工作方式相同(对不起,如果它有点冗长)。请注意,数组不会在任何地方释放,因此这会导致内存泄漏(但您应该知道传递by-value与by-pointer):

#include <iostream>
#include <string.h>

struct location
{
    std::string name;
    double lat;
    double lon;
};

location* createNewArrayAndReturnPointer(location* loc)
{
    std::cout << "-- Replacing array, name of the first location in old array is " + loc->name << std::endl;
    location* newLoc = new location[2]; //Local pointer-variable, creating new array and storing array address to it
    newLoc[0].name = "Replacing pointer by return value";

    return newLoc;  //Return new pointer
}

void modifyViaGivenPointerToPointer(location** loc_ptr_to_ptr)
{
    location* loc = *loc_ptr_to_ptr;    //De-referencing the array address from the pointer-to-pointer, storing to local pointer-variable
    std::cout << "--  Modifying pointer, name of the first location pointed originally is " + loc->name << std::endl;

    location* newLoc = new location[2]; //Creating new array and storing to local pointer-variable
    newLoc[0].name = "From modifyViaGivenPointerToPointer";
    *loc_ptr_to_ptr = newLoc;   //Replacing the contents of given pointer-variable via dereference

}

void printNameOfFirstLocationInArray(location* loc_ptr)
{
    std::cout << "The name of the first location pointer by loc_ptr is now " << loc_ptr->name << std::endl;
}

int main(void)
{
    location locations[2] = {{"Padstow", 50.5384, -4.9378},
                             {"Newquay", 50.412, -5.0757}};

    location* loc_ptr;
    loc_ptr = &locations[0];

    printNameOfFirstLocationInArray(loc_ptr);

    //Returns new pointer from function and store it in the pointer-variable
    loc_ptr = createNewArrayAndReturnPointer(loc_ptr);
    printNameOfFirstLocationInArray(loc_ptr);

    //Modifies the passed pointer-to-pointer, so it points to the new array after returning
    modifyViaGivenPointerToPointer(&loc_ptr);
    printNameOfFirstLocationInArray(loc_ptr);

    return 0;
}

输出结果为:

  

loc_ptr的第一个位置指针的名称现在是Padstow
   - 更换数组,旧数组中第一个位置的名称是Padstow
  loc_ptr的第一个位置指针的名称现在是替换指针   返回值
   - 修改指针,最初指向的第一个位置的名称是用返回值
替换指针   loc_ptr的第一个位置指针的名称现在来自modifyViaGivenPointerToPointer

答案 1 :(得分:1)

如何从函数中返回新数组

如果您要更改数组所在的地址,则需要一个双指针(指向指针的指针)。

这不起作用:

void f(location *l)
{
   // changing the array here:
   l = malloc(5*(sizeof(location));
   // add new stuff to l
}

int main()
{
    location *loc_ptr;
    loc_ptr = &locations[0];
    f(loc_ptr); // won't change address loc_ptr's is pointing to.
}

答案 2 :(得分:1)

如果你有:

struct location a;
struct location b;

a = b;

您将b中的数据副本复制到a

您似乎正在执行以下操作:

struct location *a;
struct location *b;

a = b;

b指针复制到a;不是数据。

你的意思是:

*ptr = *new_ptr;

new_ptr指向的数据复制到ptr指向的位置。

答案 3 :(得分:1)

当你这样做时

ptr = new_ptr;

我假设ptr是你函数的参数。你实际做的是覆盖堆栈上的值(指针本身的值),这不会改变函数外部指针的值。你可以传回新的指针,或者把一个双指针作为参数作为'location',然后执行:

*p_ptr = new_ptr;

答案 4 :(得分:1)

如果希望通过location变量反映数组的更改,则需要直接修改该数组。如果你宁愿对数组的副本进行所有更改,那很好,但是你必须遍历整个数组并将所有结构复制回第一个数组。

要非常小心保持数组长度相同,或者始终在某个地方保持数组长度变量。 C数组不会增长。您可以尝试使用realloc(3)增长一个,但它可能会失败,并且原始版本必须首先使用malloc(3)进行分配。如果你只是假装它们更短的话,它们可以缩小...:)

答案 5 :(得分:1)

我假设你正按照

的顺序做某事
void f(location *loc_ptr)
{
   location *new_array = ...
   loc_ptr = new_array;
}

int main(void)
{
  location locations[2] = {...};
  location *loc_ptr = locations;
  f(loc_ptr);
  ...
}

如果是,解决方案是

void f(location **loc_ptr)
{
  location *new_array = ...;
  *loc_ptr = new_array;
}

int main(void)
{
  location locations[2] = {...};
  location *loc_ptr = locations;
  f(&loc_ptr);
  ...
}

如果要更改loc_ptr的值而不是loc_ptr指向的值,则必须将指针传递给该函数。