Как мне вернуть указатель на функцию структуры одного измерения с различными структурами внутри?

У меня есть эта функция, которая должна возвращать указатель на одномерный массив различных (65 535 для этого изображения) структур. Но он возвращает только первый элемент этого массива, и мне любопытно, в чем проблема.

struct pixel* make_pixel (int red, int green, int blue){

    struct pixel* pix = malloc(sizeof(struct pixel));

    pix->blue = blue;
    pix->red = red;
    pix->green = green;

    return (pix);
}

struct pixel* read_data(FILE *stream, const struct bmp_header *header) {
    
    if(stream == NULL || header == NULL) return 0;

    struct pixel *pix = malloc(sizeof(struct pixel));

    struct pixel *data[header->width * header->height]; //would be great to do this dynamically

    for (int i = 0; i < (header->width * header->height); i++) {
        fread(pix, sizeof(struct pixel), 1, stream); //reads pixels 1 by 1 from stream
        data[i] = make_pixel(pix->red, pix->green, pix->blue); //put pixel as an i'th element of 'data' array
    }

    free(pix);

    return (*data);
}

int main() {

    const char* fileName = "C:/TheWaaay.../assets/lenna.bmp";
    FILE* image = fopen(fileName, "rb");

    struct bmp_header *header =  read_bmp_header(image);

    struct pixel *data = read_data(image, header);

    return 1;
}

Структура фактического пикселя:

struct pixel {
    uint8_t blue;
    uint8_t green;
    uint8_t red;
    //uint8_t alpha;
} __attribute__((__packed__));
# arrays pointers struct
Источник
Codelisting
за 1 против

Вы должны сделатьdata быть указателем на указатели и вернуть его.

struct pixel **read_data(FILE *stream, const struct bmp_header *header) {

    if(stream == NULL || header == NULL) return 0;

    struct pixel *pix;
    struct pixel **data; 

    pix = malloc(sizeof *pix);
    data = malloc(header->width * header->height * sizeof *data);

    for (int i = 0; i < header->width * header->height; i++) {
        fread(pix, sizeof(struct pixel), 1, stream); 
        data[i] = make_pixel(pix->red, pix->green, pix->blue); 
    }

    free(pix);

    return data;
}

main станет:

int main() {

    const char* fileName = "C:/TheWaaay.../assets/lenna.bmp";
    FILE* image = fopen(fileName, "rb");

    struct bmp_header *header =  read_bmp_header(image);

    struct pixel **data = read_data(image, header);

    for(int i = 0; i < header->width * header->height; i++) {
        // do something here with data[i]
        struct pixel *pix = data[i];
        // manipulate pix, which points to data[i]
    }

    return 1;
}
  • 0
    Деталь. Есть преимущество в sizeof *data * header->width * header->height vs. header->width * header->height * sizeof *data . Второй может int перелива продуктов , что первый делает не так , как умножение выполняется с использованием size_t повсюду.
  • 0
    К сожалению, функция read_data возвращает массив только с 1 указателем (первый пиксель). Проблема может быть в функции read_data - по некоторым причинам в вашем методе цикл всегда считывает один и тот же пиксель снова и снова. Но в любом случае спасибо за попытку помочь; )
за 0 против

dataпредставляет собой массив указателей, а не массив пикселей. Вы можете динамически выделять массив пикселей и читать прямо в него.

struct pixel* read_data(FILE *stream, const struct bmp_header *header) {

    if(stream == NULL || header == NULL) return 0;

    struct pixel *data = malloc(header->width * header->height * sizeof(struct pixel));
    if (data == NULL) {
        return NULL;
    }
    fread(&pixel[i], sizeof(struct pixel), header->width * header->height, stream);

    return data;
}
Codelisting
Популярные категории
На заметку программисту