C语言数据结构的套路

搬运自我的CSDN https://blog.csdn.net/u013213111/article/details/93784522

跟着DSAA in C写代码,总结起来各种数据结构大概都是这个套路:

首先是定义:

typedef struct XXXXX
{
    //数据结构包含的元素
} XXX

然后分配空间,malloc(sizeof(XXX))
对于用到数组来存储数据元素的,还要额外给数组分配空间,比如队列:
Q->array = malloc(sizeof(int) * max);
最后用完之后一定要记得free!

这个套路用途广泛,比如想要把图片作为一个数据结构,首先可以这么定义:

typedef struct ImgStruct
{
    uint8_t *data;
    int width;
    int height;
} Image;

然后导入图片(这里用了OpenCV,是C++,需要给函数包装一下才可以被C调用):

Image *image_import(char *img_name)
{
    Image *img;
    img = (Image *)malloc(sizeof(Image));
    cv::Mat img_mat = cv::imread(img_name, cv::IMREAD_GRAYSCALE);
    img->width = img_mat.cols;
    img->height = img_mat.rows;
    int img_size = img_mat.cols * img_mat.rows;
    img->data = (uint8_t *)malloc(img_size);
    //cv::imshow("image", img);
    for (int i = 0; i < img_mat.rows; i++)
    {
        for (int j = 0; j < img_mat.cols; j++)
        {
            img->data[i * img_mat.rows + j] = img_mat.at<uchar>(i, j);
        }
    }
    return img;
}

在main函数中只需要这样既可:

    Image *src;
    src = image_import("demo.bmp");

最后是free,设置NULL是防止悬空指针:

void image_free(Image *img)
{
    free(img->data);
    img->data = NULL;
    free(img);
    img = NULL;
}

强调一下悬空指针的问题,参考悬空指针(Dangling pointer)避免方法

什么是悬空指针?
一个指针所指的内存被释放后,这个指针就被悬空了。
悬空指针的危害?
访问悬空指针,结果随机。可能导致程序功能不正常,也可能导致程序崩溃。如果受到影响的是其它功能,问题通常很难定位。
如何避免悬空指针?
基本思路:在释放一块内存时,将指向这块内存的指针变量设置为NULL。访问指针变量前,先判断是否为NULL。
进阶:当有多个指针变量都指向同一块内存时,释放这块内存时,需要将所有指针变量的值都置为NULL,这需要维护所有指向这块内存的指针变量的信息,但是这种方式开销大,所以通常很少使用。使用频率不是非常高的对象,可以在使用前先根据id等索引查找,如果找不到,则不要使用。如果有使用者时,不能释放这块内存,我们可以使用引用计数,只有当引用计数为0时,才真正释放内存,否则,只是引用计数减1。

BTW,DSAA中数据结构的各种函数多是传指针作为参数,传值的方法当然也可以,两者的区别可以参考C语言 结构体传值与传址分析

结构体对象作为参数时,编译器对其进行了copy,(我们通过传入的地址和main中不同可以发现)。此时在函数中的操作都是对其拷贝的操作,不影响main函数中的origin value。缺点是,当结构体变量非常大时,编译器对其进行复制,开销较大。结构体地址作为参数时,子函数中操作和main函数操作的是同一个结构体,此时传递的参数时一个地址。优点是不需要进行copy,但是使用时要小心,如果不想修改其值,需用const关键字修饰。

猜你喜欢

转载自www.cnblogs.com/lyrich/p/11110596.html