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

标签 c arrays pointers math

我正在为 OSX 编写 C 语言,在 64 位机器上以 32 位模式运行。我正在使用 GCC for 386 进行编译。项目很大;我没有看到编译器有任何奇怪的行为(可能直到现在)。应用程序是多线程的,这段代码本来就是这样,但此时正在单线程运行。我正在使用与位置无关的 clib 进行编译,并在线程化时使用 posix 线程。顺便说一句,如果我对它进行线程处理,这段代码的行为完全相同。

以下是一个简化的过程,以最简单的形式演示了该问题。基本上,我在这里将 16 位图像 channel 从一组三个 RGB channel (mr,mg,mb) 移动到另一组大小完全相同的 3 个 RGB channel (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];
            }
        }
    }
}

如您所见,图像边缘和边缘内部的 Action 是相同的;我只是在移动数据。这行得通——它的输出是 lr、lg 和 lb channel 中的图像。

但。如果在 else 子句中,我将这些行更改为...
            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 环境中。我尝试过使用偶数偏移,认为编译器可能对数据的大小感到困惑。我每次都得到相同的结果。偏移值可以按原样使用,但只能按原样使用。不能在括号内修改,更不能在括号外修改,只是被当作一个long来处理。

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

一点背景;这是一个 RIP(删除孤立像素)操作,或者至少,如果我能得到循环当前正在查看的像素周围的 8 个像素,它会是。这就是为什么对边缘进行不同处理的原因;我不想在边缘运行 8 像素环视,只在其中我将始终查看所有 8 个像素:
ooo
oxo
ooo

在这个测试用例中,我删除了所有的 RIP 代码,因为它增加了很多复杂性并且没有说明问题。这只是(哈!)数组和指针偏移似乎无法正常工作的情况。

最佳答案

您的索引函数假定二维数组位于 row-major order .

offset = (y * xw) + x;

也许它们是列主要的顺序。

关于c - 我的无符号短指针返回意外结果。为什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4871212/

相关文章:

为斐波那契数列创建表

c - 如何将结构视为内存位置并使用指针分别访问元素

Java - 在矩阵行或列上应用 vector 方法

c# - 获取索引并将值添加到等效索引

c - 由于排序功能导致的段错误

c - 让函数更改指针在 C 中表示的值

c 在 float 中用逗号替换点

c - 跟随一个指向指针的指针

javascript - 将键值对转换为数组javascript

c - 当 realloc 缩小分配的 block 时,释放的内存在哪里?