我的无符号短指针正在返回意外结果。为什么?

时间:2011-02-02 05:51:09

标签: c arrays pointers math

我正在用C语言编写OSX,在32位模式下运行在64位机器上。我正在使用GCC编译386。项目很大;我没有看到编译器的任何奇怪行为(可能直到现在。)应用程序是多线程的,并且此代码应该是,但此时正在运行单线程。我正在使用位置无关的clib进行编译,并在线程化时使用posix线程。如果我线程,那么这段代码btw的行为完全相同。

以下是以最简单的形式演示问题的简化程序。基本上,我将这里的16位图像通道从一组三个RGB通道(mr,mg,mb)移动到另一组完全相同大小的3个RGB通道(lr,lg,lb)。片段,因为我即将转储它,完美地工作:

void lrip_me(   unsigned short *mr, // RIP from source image
                unsigned short *mg,
                unsigned short *mb,
                unsigned short *lr, // into RGB layer
                unsigned short *lg,
                unsigned short *lb,
                struct layer *lay,
                long start,long finish)
{
long xw,yw;
long xf,yf;
long x,y;
unsigned long offset;

    xw = lay->parent->x;
    yw = lay->parent->y;
    xf = xw - 1;
    yf = yw - 1;

    for (y=start; y<finish; y++)
    {
        for (x=0; x<xw; x++)
        {
            offset = (y * xw) + x;
            if (x==0 || x==xf || y==0 || y==yf) // then on edge
            {
                lr[offset] = mr[offset];
                lg[offset] = mg[offset];
                lb[offset] = mb[offset];
            }
            else
            {
                lr[offset] = mr[offset];
                lg[offset] = mg[offset];
                lb[offset] = mb[offset];
            }
        }
    }
}

如您所见,图像边缘和边缘内部的动作是相同的;我只是移动数据。这是有效的 - 它的输出是lr,lg和lb通道中的图像。

BUT。如果,在else子句中,我将行更改为read ...

            lr[offset] = mr[offset-xw];
            lg[offset] = mg[offset-xw];
            lb[offset] = mb[offset-xw];

...您希望图像内部移动一条扫描线,因为数据提取将来自完整扫描线的距离,但会转移到未移位的目标位置。相反,输出看起来完全随机。就像短裤被装在错误的边界上,或许是从其他地方。这也是做同样的事情......

            lr[offset] = mr[offset-1];
            lg[offset] = mg[offset-1];
            lb[offset] = mb[offset-1];

...在那里,我希望图像水平移动一个像素。不。相同的结果 - 最纯粹的哈希。

我尝试过更改为指针数学而不是数组// *(mr + offset-1)//并获得完全相同的结果。我已经在库中和objc环境中编译了它。我试过使用偶数偏移,认为编译器可能对数据的大小感到困惑。我每次都得到相同的结果。偏移值可以按原样使用,但只能按原样使用。它不能在括号内修改,而且,它不能在括号外修改,只是被视为长。

我不知道这里发生了什么。如果有人能帮助我了解它是什么,我一定会很感激。

一点背景;这是一个RIP(去除孤立的像素)操作,或者至少,如果我可以得到循环当前正在查看的那个周围的8个像素。这就是边缘被区别对待的原因;我不想在边缘上运行8像素的外观,只在其中我将始终拥有所有8个内容:

ooo
oxo
ooo

在这个测试用例中,我删除了所有的RIP代码,因为它增加了很多复杂性并且没有解决问题。这简直就是(哈!)一个数组和指针偏移看起来不合理的情况。

1 个答案:

答案 0 :(得分:1)

您的索引函数假设2D数组位于row-major order

offset = (y * xw) + x;

也许他们是按照专栏的顺序。