为什么我的小 C 循环不能正确打印到帧缓冲区,但它的展开版本可以?

Why doesn't my small C loop print correctly to the frame buffer, but its unrolled version does?

我正在尝试编写一个简单的 C 程序,在位置 (x, y) = (50, 50) 处绘制一个 4x4 像素的白色实心正方形。

想法是直接写入 Linux 帧缓冲区,它从映射内存 fb->fp 开始。

现在,问题是以下代码运行良好:

uint16_t color = 0xffff;

memcpy(fb->fp + (50+0) * fb->line_length + (50+0) * fb->bytes_per_pixel, &color, fb->bytes_per_pixel);
memcpy(fb->fp + (50+0) * fb->line_length + (50+1) * fb->bytes_per_pixel, &color, fb->bytes_per_pixel);
memcpy(fb->fp + (50+0) * fb->line_length + (50+2) * fb->bytes_per_pixel, &color, fb->bytes_per_pixel);
memcpy(fb->fp + (50+0) * fb->line_length + (50+3) * fb->bytes_per_pixel, &color, fb->bytes_per_pixel);

memcpy(fb->fp + (50+1) * fb->line_length + (50+0) * fb->bytes_per_pixel, &color, fb->bytes_per_pixel);
memcpy(fb->fp + (50+1) * fb->line_length + (50+1) * fb->bytes_per_pixel, &color, fb->bytes_per_pixel);
memcpy(fb->fp + (50+1) * fb->line_length + (50+2) * fb->bytes_per_pixel, &color, fb->bytes_per_pixel);
memcpy(fb->fp + (50+1) * fb->line_length + (50+3) * fb->bytes_per_pixel, &color, fb->bytes_per_pixel);

memcpy(fb->fp + (50+2) * fb->line_length + (50+0) * fb->bytes_per_pixel, &color, fb->bytes_per_pixel);
memcpy(fb->fp + (50+2) * fb->line_length + (50+1) * fb->bytes_per_pixel, &color, fb->bytes_per_pixel);
memcpy(fb->fp + (50+2) * fb->line_length + (50+2) * fb->bytes_per_pixel, &color, fb->bytes_per_pixel);
memcpy(fb->fp + (50+2) * fb->line_length + (50+3) * fb->bytes_per_pixel, &color, fb->bytes_per_pixel);

memcpy(fb->fp + (50+3) * fb->line_length + (50+0) * fb->bytes_per_pixel, &color, fb->bytes_per_pixel);
memcpy(fb->fp + (50+3) * fb->line_length + (50+1) * fb->bytes_per_pixel, &color, fb->bytes_per_pixel);
memcpy(fb->fp + (50+3) * fb->line_length + (50+2) * fb->bytes_per_pixel, &color, fb->bytes_per_pixel);
memcpy(fb->fp + (50+3) * fb->line_length + (50+3) * fb->bytes_per_pixel, &color, fb->bytes_per_pixel);

然而,下面没有。 它生成 1x4 线而不是 4x4 正方形。

uint16_t color = 0xffff;

int i = 0;
int j = 0;
for (; j < 4; j++) {
    for (; i < 4; i++) {

        int y_offset = 50 + j;
        int x_offset = 50 + i;

        memcpy(fb->fp + y_offset * fb->line_length + x_offset * fb->bytes_per_pixel, 
               &color, fb->bytes_per_pixel);
    }
}

据我所知,它们应该是等价的。 我从编译器得到的汇编版本看起来不太好理解。

这在 ARM 嵌入式 Linux 设备中运行。 此时没有 X 服务器或任何其他内容写入帧缓冲区。

fb->bytes_per_pixel 等于 2.

我找不到任何关于帧缓冲区是如何映射到内存的文档。我得到的偏移量来自我在 Google.

上找到的随机代码

也许这些偏移量有问题。 但至少这两个代码应该是等价的,不是吗? 我要疯了吗?

这是问题所在:

for (; j < 4; j++) {
    for (; i < 4; i++) {
        //some code
    }
}

for循环预计执行4次,这一定是因为循环体中没有条件break;语句。 然而,内部 for 循环需要更改。对于外部 for 循环的第一次迭代,内部 for 循环按预期执行了 4 次。
外层for循环的第二次迭代,i的值为4,内层for循环的条件i>4为假,所以不会'执行。外部 for 循环的所有下一次迭代都会发生同样的情况。

您可以通过为外部 for 循环的每次迭代初始化 i 来克服这个问题。

选项 1:

for( ; j < 4; j++)
{
    for (i = 0; i < 4; i++)
    {
        // Some code
    }
}

选项 2:

for( ; j < 4; j++)
{
    for (; i < 4; i++)
    {
        // Some code
    }
    i = 0;
}

选项 3:

for( ; j < 4; j++)
{
    i = 0;
    for ( ; i < 4; i++)
    {
        // Some code
    }
}

选项 4:根据 David C. Rankin 的建议:

int j = 0;
// int i = 0;
for( ; j < 4; j++)
{
    int i = 0;
    for ( ; i < 4; i++)
    {
        // Some code
    }
}