简体   繁体   English

在结构内使用指针

[英]Using pointer inside a struct

Suppose I have the following: 假设我有以下内容:

#include <stdio.h>

typedef struct
{
    int num;
} myObj;

typedef struct
{
    myObj *obj_ptr;
} myStruct;

void populate(myStruct *m1)
{
    m1->obj_ptr->num = 123;
}

int main()
{
    printf("Hello World");
    myStruct m1;
    populate(&m1);

    printf("%d", m1.obj_ptr->num);

    return 0;
}

The purpose of this code is I want to get an item eg m1 populated instead of being returned by the populate function, hence the way it is coded. 这段代码的目的是我想要填充一个项目,例如m1而不是由populate函数返回它,因此要对其进行编码。

I'm concerned about the line m1.obj_ptr->num since it doesn't seem like a good design. 我担心m1.obj_ptr->num因为它似乎不是一个好的设计。 Are there any issues with this code even as I got it to run? 即使我开始运行,此代码也有问题吗? Is there a better approach to this? 有更好的方法吗?

It is OK to have a pointer in a struct, you must however allocate memory for it: 在结构体中有一个指针是可以的,但是您必须为其分配内存:

void populate(myStruct *m1)
{
    m1->obj_ptr->num = 123;
}

is wrong, because m1->obj_ptr is not initialized. 是错误的,因为未初始化m1->obj_ptr You can do this: 你可以这样做:

void populate(myStruct *m1)
{
    // always check for validity of arguments
    if(m1 == NULL)
        return;

    m1->obj_ptr = malloc(sizeof *m1->obj_ptr);
    if(m1->obj_ptr == NULL)
        return;

    m1->obj_ptr->num = 123;
}

I personally would make populate return 1 on success and 0 on failure, thus the caller knows if the allocation was successful. 我个人将使populate成功返回1,失败返回0,因此调用者知道分配是否成功。

But you don't have to forget to free the memory: 但是您不必忘记释放内存:

int main()
{
    printf("Hello World");
    myStruct m1;
    populate(&m1);

    if(m1.obj_ptr)
        printf("%d", m1.obj_ptr->num);

    free(m1.obj_ptr);

    return 0;
}

If you say, you don't want to allocate memory in populate , then you have to initialize the pointer prior to the call of the populate , like this: 如果说,您不想在populate分配内存,则必须在调用populate之前初始化指针,如下所示:

int main()
{
    printf("Hello World");
    myStruct m1;
    myObj obj;

    m1.obj_ptr = &obj;

    populate(&m1);

    printf("%d", m1.obj_ptr->num);

    return 0;
}

But this has the disadvantage that you cannot return this struct to another function. 但这有一个缺点,即您无法将此结构返回给另一个函数。 This would be incorrect: 这将是不正确的:

myStruct get_me_a_struct(void)
{
    myStruct m1;
    myObj obj;

    m1.obj_ptr = &obj;

    populate(&m1);

    return m1;
}

void foo(void)
{
    myStruct m2 = get_me_a_struct();

    printf("%d\n", m2.obj_ptr->num); // <-- you cannot do that
}

because m2.obj_ptr would point to an invalid location. 因为m2.obj_ptr会指向无效的位置。 For that reason, using malloc for the allocation is better. 因此,最好使用malloc进行分配。

Two things; 两件事情; both within populate() : 都在populate()

First, nowhere are you allocating or deallocating the space for obj_ptr in your code. 首先,您没有在代码中为obj_ptr分配或取消分配空间的obj_ptr You simply set the value of num within in it and hope for the best. 您只需在其中设置num的值,并希望达到最佳效果。 Before the line m1->obj_ptr->num = 123; m1->obj_ptr->num = 123;行之前m1->obj_ptr->num = 123; allocate some memory for that 123 to live in with m1->obj_ptr = malloc(sizeof(myObj)) . 使用m1->obj_ptr = malloc(sizeof(myObj))为该123分配一些内存。 Without this, when you set num it is actually pointeing to an unknown memory address which is probably not set aside for your program to work in. 没有这个,当你设置num它实际上指向一个未知的内存地址,该地址可能没有留给程序使用。

Similarly, populate() does not check whether m1 is a valid address before assigning to its members. 同样, populate()在分配给m1成员之前不会检查m1是否为有效地址。 In this sample code, it is (only mostly) okay, because when you call populate() you are passing a reference( & ) rather than a pointer( * ), but, if you ever use it in the future, you may be calling with a pointer. 在此示例代码中,(大多数情况下)还可以,因为当您调用populate()您传递的是引用( & )而不是指针( * ),但是,如果将来使用它,您可能会用指针调用。 So really, the first line in populate() needs to be if(m1 != NULL) with the rest of the function inside. 因此,实际上, populate()的第一行必须为if(m1 != NULL) ,其余函数都在内部。

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

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