7

C语言结构体里只有一个成员,有什么特别意义吗?

 3 years ago
source link: https://blog.popkx.com/there-is-only-one-member-in-the-c-language-structure-is-there-any-special-significance/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

C语言结构体里只有一个成员,有什么特别意义吗?

发表于 2019-01-30 21:01:17   |   已被 访问: 642 次   |   分类于:   C语言   |   暂无评论

今天看 linux 内核代码时,发现了结构体中只有一个成员的数据结构,事实上,在 linux 内核中,这种结构相当常见。举例如下:

struct rb_root
{
    struct rb_node *rb_node;
};

一开始,我觉得这样无非就是为了方便突出 rb_root 的特异性(虽然它也是一个节点,但是 root 节点),或者方便以后扩展。但今天我的脑海里却灵光一闪,发现采用这种数据结构,其实更方便的点在于:能够避免使用多级指针

7df5da4809835689c3a85db00da77342.png

在我之前的文章里讨论过,C语言使用指针做参数常常能够提高程序紧凑型,和运行效率。事实上,struct rb_root 数据结构是用于定义红黑树根节点的,红黑树的根节点可能会在某次着色变换中改变,这时如果仅仅使用 struct rb_node 来定义根节点指针,负责“改变”根节点的函数就需要二级指针做参数了。

需要使用二级指针的例子

这样说可能有些懵,我们还是来看实例吧。假设在某个函数中,需要 malloc 一块内存:

char *p = (char*)malloc(10);

使用完毕后,我们应该将其释放,而且应该让 p 指向 NULL,原因我之前的文章解释过。

if(p){
    free(p);
    p = NULL;
}
9f1b3cd6b34df55456cff070258e6282.png

如果需要频繁的释放 p,每次这么写代码就太繁琐了,那能否定义一个函数完成这两个步骤呢?当然是可以的,请看以下C语言代码:
void my_free(char* p){
    if(p){
        free(p);
        p = NULL;
    }
}
// p != NULL
my_free(p);
// p != NULL

my_free() 函数的确能够释放 p,但是却无法完成将 p 指向 NULL 的操作。原因我的这篇文章已经解释过。若想实现我们的计划,需要借助二级指针才可以,请看如下C语言代码:

void my_free(char** p){
    if(*p){
        free(*p);
        *p = NULL;
    }
}
// p != NULL
my_free(&p);
// p == NULL
dc1ae1be512fe3a85e2ec86a3bfab93a.png

使用二级指针的确能够解决问题,但是它也让代码变得不那么直观了,使用起来也不是特别方便,所以可以借助文章一开头提到的那种数据结构。
805a6aa07518430f61cb4ad6957a4e44.png

避免使用二级指针

先来定义数据结构如下,请看C语言代码:

struct PTR
{
     char*   data;
};

之后我们 malloc 和 free 时都使用 PTR 的成员 data,就能避免使用二级指针了,请看下面的C语言代码:

void my_free(struct PTR* ptr)
{
    if(ptr){
        if(ptr->data){
            free(ptr->data);
            ptr->data = NULL;
        }
    }
}

int main()
{
    struct PTR ptr;

    ptr.data = (char*)malloc(10);
    if(NULL==ptr.data)
        exit(110);

    printf("before free, data: %p\n", ptr.data);
    my_free(&ptr);
    printf("after free, data: %p\n", ptr.data);

    return 0;
}
69e993b8fe62ef2927d01a91eb10a9f9.png

这样我们就避免了使用二级指针,编译C语言程序,执行结果如下:

阅读更多:   C语言


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK