繁体   English   中英

将结构数组分配给指针

[英]Assigning struct array to pointer

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

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;
}    

但是,它不会更改原始数据。 您能解释一下我为将这个新数组分配给原始指针所做的错误操作吗?

我已经有一段时间没有用C做任何事了,所以我有点生锈,但是我会尝试一下...

我将看到(至少)两种方法可以使此工作正常进行:从函数返回新数组的新指针,并将其存储在旧指针中,例如(在语法上可能不正确):

loc_ptr = someFunctionCreatingTheNewArrayAndReturningAPointerToIt(loc_ptr);

另一种可能性是将loc_ptr传递给函数的按指针而不是按值。 基本上,您将“指针到指针”作为参数传递给函数,指针到指针指向loc_ptr。 在函数内部,可以从指针到指针解引用数组的内存地址以访问原始数组。 创建并填充新数组后,将新数组的内存地址放入由指针传递的参数中。

编辑:我整理了两种方法的快速示例,这实际上是在C ++中,但是我99%确信,指针在C中的工作原理相同(对不起,如果有点冗长)。 请注意,数组不会在任何地方释放,因此这会导致内存泄漏(但是您应该获得传递按值与按指针传递的想法):

#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的第一个位置指针的名称现在为From ModifyViaGivenPointerToPointer

您如何从函数中返回新数组

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

这不起作用:

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.
}

如果你有:

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指向的位置。

当你做

ptr = new_ptr;

我假设ptr是您函数的参数。 您实际上所做的是覆盖堆栈上的值(指针本身的值),这不会更改函数外部的指针值。 您可以传回新指针,也可以将指向“位置”的双指针作为参数,然后执行以下操作:

*p_ptr = new_ptr;

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

要非常小心,以保持数组长度相同,或者始终将数组长度变量保持在永不增长的位置。 C数组不会增长。 您可以尝试使用realloc(3)进行realloc(3) ,但可能会失败,并且首先必须使用malloc(3)分配原始文件。 它们可以收缩,有点,如果您只是假装它们更短... :)

我认为您正在按以下顺序进行操作

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指向的值, loc_ptr必须将指向它的指针传递给函数。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM