简体   繁体   English

将结构数组分配给指针

[英]Assigning struct array to pointer

I have initialised an array of structs (containing just a char string called name . This struct array is then assigned to a pointer, like so: 我已经初始化了一个结构数组(仅包含一个名为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);

I am then passing this pointer into a function. 然后,我将此指针传递给一个函数。 Inside this function, I am removing an element of the array. 在此函数内部,我正在删除数组的元素。 This is done by iterating through the current array, and creating a new array. 这可以通过遍历当前数组并创建一个新数组来完成。 The new array contains the data I expect. 新数组包含我期望的数据。

Inside the remove_element function: 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;
}    

However, it is not changing the original data. 但是,它不会更改原始数据。 Could you explain what I am doing incorrectly to assign this new array to my original pointer? 您能解释一下我为将这个新数组分配给原始指针所做的错误操作吗?

I haven't done anything in C for quite a while, so I'm a bit rusty, but I'll give it a try... 我已经有一段时间没有用C做任何事了,所以我有点生锈,但是我会尝试一下...

I'd see there are (at least) two ways to get this working: either return the new pointer for the new array from the function and store it in the old pointer, something like (this might be syntactically incorrect): 我将看到(至少)两种方法可以使此工作正常进行:从函数返回新数组的新指针,并将其存储在旧指针中,例如(在语法上可能不正确):

loc_ptr = someFunctionCreatingTheNewArrayAndReturningAPointerToIt(loc_ptr);

Another possibility is to pass the loc_ptr to the function by-pointer instead of by-value. 另一种可能性是将loc_ptr传递给函数的按指针而不是按值。 Basically, you'll pass a "pointer-to-pointer" as parameter into the function, the pointer-to-pointer pointing to you loc_ptr. 基本上,您将“指针到指针”作为参数传递给函数,指针到指针指向loc_ptr。 Inside the function, you dereference the arrays memoryaddress from the pointer-to-pointer to access the original array. 在函数内部,可以从指针到指针解引用数组的内存地址以访问原始数组。 Once you've created and filled the new array, put the memory address of the new array into the parameter passed by-pointer. 创建并填充新数组后,将新数组的内存地址放入由指针传递的参数中。

Edit: I whipped up a quick example of both ways, this is actually in C++, but I'm 99% sure, that the pointers work the same in C (sorry if it's a bit verbose). 编辑:我整理了两种方法的快速示例,这实际上是在C ++中,但是我99%确信,指针在C中的工作原理相同(对不起,如果有点冗长)。 Note that the arrays aren't freed anywhere, so this would cause memory leaks (but you should get the idea of passing by-value vs. 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;
}

The output is: 输出为:

The name of the first location pointer by loc_ptr is now Padstow loc_ptr的第一个位置指针的名称现在为Padstow
-- Replacing array, name of the first location in old array is Padstow -替换阵列,旧阵列中第一个位置的名称为Padstow
The name of the first location pointer by loc_ptr is now Replacing pointer by return value loc_ptr的第一个位置指针的名称现在是按返回值替换指针
-- Modifying pointer, name of the first location pointed originally is Replacing pointer by return value -修改指针,最初指向的第一个位置的名称是用返回值替换指针
The name of the first location pointer by loc_ptr is now From modifyViaGivenPointerToPointer loc_ptr的第一个位置指针的名称现在为From ModifyViaGivenPointerToPointer

How are you returning the new array from your function. 您如何从函数中返回新数组

If you are going to change the address where the array resides, you will need a double pointer (pointer to pointer). 如果要更改数组所在的地址 ,则需要一个双指针(指向指针的指针)。

This won't work: 这不起作用:

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

If you have: 如果你有:

struct location a;
struct location b;

a = b;

you will make a copy of the data in b into a . 您将把b中的数据复制到a

You seem to be doing the following: 您似乎正在执行以下操作:

struct location *a;
struct location *b;

a = b;

This copies the pointer of b into a ; 这会将b指针复制到a not the data. 不是数据。

What you perhaps mean is: 您可能的意思是:

*ptr = *new_ptr;

To copy the data pointed to by new_ptr into the location pointed to by ptr . new_ptr指向的数据复制到ptr指向的位置。

When you do 当你做

ptr = new_ptr;

I'm assuming that ptr is the parameter to your function. 我假设ptr是您函数的参数。 What you are actually doing is overriding the value on the stack (the value of the pointer itself), which will not change the value of the pointer outside the function. 您实际上所做的是覆盖堆栈上的值(指针本身的值),这不会更改函数外部的指针值。 You can either pass back the new pointer, or take as an argument a double pointer to 'location', and then do: 您可以传回新指针,也可以将指向“位置”的双指针作为参数,然后执行以下操作:

*p_ptr = new_ptr;

If you want changes to the array to be reflected through the location variable, then you will need to modify that array directly, in place. 如果要通过location变量反映对阵列的更改,则需要直接就地修改该阵列。 If you'd rather make all your changes to a copy of the array, that is fine, but then you must loop through the entire array and copy all structs back to the first array. 如果您希望对数组的副本进行所有更改,那很好,但是您必须遍历整个数组并将所有结构复制回到第一个数组。

Be very careful to keep the array lengths the same OR always maintain an array-length variable somewhere that NEVER GROWS. 要非常小心,以保持数组长度相同,或者始终将数组长度变量保持在永不增长的位置。 C arrays do not grow. C数组不会增长。 You can try growing one with realloc(3) , but it can fail, and the original must be allocated with malloc(3) in the first place. 您可以尝试使用realloc(3)进行realloc(3) ,但可能会失败,并且首先必须使用malloc(3)分配原始文件。 They can shrink, sort of, if you just pretend they are shorter... :) 它们可以收缩,有点,如果您只是假装它们更短... :)

I assume you're doing something on the order of 我认为您正在按以下顺序进行操作

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

If so, the solution is 如果是这样,解决方案是

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

If you want to change the value of loc_ptr rather than what loc_ptr points to, you must pass a pointer to it to the function. 如果要更改loc_ptr的值而不是loc_ptr指向的值, loc_ptr必须将指向它的指针传递给函数。

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

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