ANSI C:如何在结构域上进行抽象?

时间:2017-04-23 14:51:58

标签: c c89

我的图像表示为RGB像素的2D数组。

typedef struct {
    char R;
    char G;
    char B;
} RGB;

和为该图像计算每个像素的新颜色的函数:

RGB new_color(RGB image[][], int r, int c){
    RGB color;
    color.R = image[r][c].R + image[r+1][c].R + image[r-1][c].R + image[r][c+1].R + image[r][c-1].R;
    color.G = image[r][c].G + image[r+1][c].G + image[r-1][c].G + image[r][c+1].G + image[r][c-1].G;
    color.B = image[r][c].B + image[r+1][c].B + image[r-1][c].B + image[r][c+1].B + image[r][c-1].B;
    return color;
}

是否可以删除new_color正文中的代码重复?换句话说,抽象出RGB数据结构的字段名称?

1 个答案:

答案 0 :(得分:5)

我们现在忽略RGB image[][]在C89中不合法。

您可以分解访问者功能。

char *get_RGB_R(RGB* rgb) { return &rgb->R; }
char *get_RGB_G(RGB* rgb) { return &rgb->G; }
char *get_RGB_B(RGB* rgb) { return &rgb->B; }

然后编写一个使用它们的辅助函数。

void set_color_channel_from_adjacent(
    char *(*accessor)(RGB*), RGB* result, RGB image[][], int r, int c)
{
    *accessor(result) = *accessor(&image[r][c]) +
                        *accessor(&image[r+1][c]) + 
                        *accessor(&image[r-1][c]) + 
                        *accessor(&image[r][c+1]) + 
                        *accessor(&image[r][c-1]);
}

然后调用辅助函数

RGB new_color(RGB image[][], int r, int c)
{
    RGB color;
    set_color_channel_from_adjacent(get_RGB_R, &color, image, r, c);
    set_color_channel_from_adjacent(get_RGB_G, &color, image, r, c);
    set_color_channel_from_adjacent(get_RGB_B, &color, image, r, c);
    return color;
}

现代编译器将内联短函数并生成与原始函数等效的代码。