我有一个与bmp和im相关的学校项目,我有点拘泥于事物的动态分配方面(因为我被要求使用它)。
我要做的是使用指针传递数组,这样即使在函数结束后数组也会更改其值,这就是我使用**的原因。然而,由于这一点,代码最终崩溃了(因为没有它,代码运行得很顺利),我确信这是我对*的错误使用,但我不知道在哪里以及如何修复它。

typedef struct pixel{unsigned int r,g,b;}pixel;
void liniarizare(char *filename,pixel **liniar)
{int i;
 ... (i calculate size which is surely correct and declare fin;size=width*height*sizeof(pixel)
*liniar=(pixel*)malloc(size);
for (i=0;i<width*height;i++)
    {fread(&liniar[i]->b,1,1,fin);
     fread(&liniar[i]->g,1,1,fin);
     fread(&liniar[i]->r,1,1,fin);
     }
 }
...
int main()
{...
 pixel *liniar
 liniarizare(filename,&liniar);
 ....}

最佳答案

请注意,这是我的头条评论。
也就是说,让函数返回pixel *。并且,使用一个额外的unsigned char变量来防止将一个字节读入unsigned int
以下是我认为应该有效的简化版本:

typedef struct pixel {
    unsigned int r;
    unsigned int g;
    unsigned int b;
} pixel;

pixel *
liniarizare(char *filename)
{
    int i;

    int count = width * height;
    int size = sizeof(pixel) * count;
    pixel *liniar = malloc(size);

    pixel *pix = liniar;
    unsigned char byte;
    for (i = 0; i < count; ++i, ++pix) {
        fread(&byte,1,1,fin);
        pix->b = byte;

        fread(&byte,1,1,fin);
        pix->g = byte;

        fread(&byte,1,1,fin);
        pix->r = byte;
    }

    return liniar;
}

int
main(void)
{
    pixel *liniar;

    liniar = liniarizare(filename);

    return 0;
}

更新:
奇迹般地足够了。唯一的问题是,我需要能够通过函数中的“reference”传递数组,并让函数提供修改后的数组,这就是为什么我坚持使用**void的原因。你知道我的代码有什么问题吗?你说了些错话。
好吧,处理“return”双星参数(例如linear[i]->b)的最简单/最好的方法是尽可能忽略这一点。
也就是说,函数在内部处理更简单的whatever **retptr。这更快,因为在每个语句上只有一个解引用级别,而没有一个双解引用。
返回值(即双星指针)只在末尾设置一次。
下面是我的示例,它被修改为使用您的原始函数原型(但与我的其他清理一起使用)。请注意,只更改了两行(函数原型和函数的最后一行):
typedef struct pixel {
    unsigned int r;
    unsigned int g;
    unsigned int b;
} pixel;

void
liniarizare(char *filename,pixel **retval)
{
    int i;

    int count = width * height;
    int size = sizeof(pixel) * count;
    pixel *liniar = malloc(size);

    pixel *pix = liniar;
    unsigned char byte;
    for (i = 0; i < count; ++i, ++pix) {
        fread(&byte,1,1,fin);
        pix->b = byte;

        fread(&byte,1,1,fin);
        pix->g = byte;

        fread(&byte,1,1,fin);
        pix->r = byte;
    }

    *retval = liniar;
}

int
main(void)
{
    pixel *liniar;

    liniarizare(filename,&liniar);

    return 0;
}

有时需要在函数的顶部读取“返回值”指针,并在底部进行设置。
这里有一个“push to tail”函数,用于单链表:
void
push(node **list,node *new)
{
    node *head;
    node *prev;
    node *cur;

    head = *list;

    prev = NULL;
    for (cur = head;  cur != NULL;  cur = cur->next)
        prev = cur;

    if (prev != NULL)
        prev->next = new;
    else
        head = new;

    new->next = NULL;

    *list = head;
}

更新2:
好吧,现在我们有了一些工作,是时候优化它了(在适当的休息期之后:-)。
保留当前工作版本作为参考/交叉检查。
whatever *ptr对单个字节的调用有些昂贵。
由于您的代码在一次I/O中执行字节操作,我们可以用fread替换fread调用。这应该稍微快一点:
for (i = 0; i < count; ++i, ++pix) {
    pix->b = fgetc(fin) & 0xFF;
    pix->g = fgetc(fin) & 0xFF;
    pix->r = fgetc(fin) & 0xFF;
}

不过,我们想尽可能多地读一段。要在一个fgetc调用中读取整个图像,需要一个fread的临时数组。这可能是内存太多,读取大图像可能会遇到缓存命中/未命中问题。
但我们可以一次排一排(例如unsigned char image[count];)。这更容易处理,而且可能产生好的或更好的结果,所以这可能是一个很好的折衷方案。
这可能更快,也可能更快。这就是为什么我们会保留其他版本并进行基准测试,以确定最快/最好的版本。
注意,这段代码假设X维中的像素在物理上是相邻的[一种合理的可能性],但是即使矩阵被转置,仍然可以工作最后,它仍然按照原始代码的线性顺序读取unsigned char row[width * 3];像素:
typedef struct pixel {
    unsigned int r;
    unsigned int g;
    unsigned int b;
} pixel;

void
liniarizare_by_row(char *filename,pixel **retval)
{
    int i;
    int yidx;

    int count = width * height;
    int size = sizeof(pixel) * count;
    int w3 = width * 3;
    pixel *liniar = malloc(size);

    pixel *pix = liniar;
    unsigned char row[w3];
    for (yidx = 0;  yidx < height;  ++yidx) {
        fread(row,sizeof(row),1,fin);
        for (i = 0;  i < w3;  i += 3, ++pix) {
            pix->b = row[i + 0];
            pix->g = row[i + 1];
            pix->r = row[i + 2]
        }
    }

    *retval = liniar;
}

int
main(void)
{
    pixel *liniar;
    pixel *liniar_fast;

    liniarizare(filename,&liniar);
    liniarizare_fast(filename,&liniar_fast);

    return 0;
}

关于c - 功能中动态分配的结构,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/54013617/

10-11 05:38
查看更多