2011-02-02 7 views
3

32ビットモードの64ビットマシンで動作するOSX用のC言語で書いています。私はGCCを使って386をコンパイルしています。私はコンパイラからの奇妙な動作を見たことがありません(おそらく今まで)。アプリケーションはマルチスレッドであり、このコードは実行されていますが、現時点ではシングルスレッドで実行されています。私はポジションに依存しないclibを使用してコンパイルしており、スレッディング時にposixスレッドを使用しています。このコードは、もし私がを実行した場合、全く同じように動作します。スレッドです。私の署名のないショートポインタが予期しない結果を返しています。どうして?

以下は、問題を最も簡単な形で示す簡単な手順です。基本的には、ここでは3つのRGBチャンネル(mr、mg、mb)のセットから16ビットの画像チャンネルをまったく同じサイズの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チャンネルの画像です。

しかし、場合は、else節の内側に、私は読んで行を変更...

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

...あなたは、データのフェッチから来されるように、1本の走査線を移動するために、画像の内部を期待します全走査線の距離は離れているが、シフトされていない目標位置に行く。代わりに、出力は完全にランダムに見えます。ショートパンツのように間違った境界に、おそらく、または他の場所からロードされました。これは同じことです...

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

...そこには、画像が水平方向に1画素移動すると思います。同じ結果 - 純粋なハッシュ。

私は配列// *(mr + offset-1)//の代わりにポインタ演算に変更しようとしましたが、まったく同じ結果を得ました。私はそれをライブラリとobjc環境の中でコンパイルしました。私はオフセットを使ってみましたが、おそらくコンパイラはデータのサイズについて混乱していると思います。毎回同じ結果が出ます。オフセット値はそのまま使用できますが、そのまま使用してください。括弧の中で変更することはできません。また、大括弧の外側で変更することはできません。

ここで何が起こっているのかわかりません。誰かが何かを理解するのを助けるなら、私は確かにそれを感謝します。

少し背景。これはRIP(孤立したピクセルを削除する)操作であり、少なくともループが現在見ている8ピクセルを得ることができるならば、少なくともそれはなります。そういうわけで、エッジが異なって扱われるのです。このテストケースでは

ooo 
oxo 
ooo 

、私はすべてのRIPを削除しました:私は常にすべての8を見ているだろう場所だけそれらの内側に、エッジに8ピクセルの前後参照を実行したくありませんコードは、複雑さが増し、問題を明らかにしません。これは単純に(ハッ!)配列とポインタのオフセットが分かりやすく機能していないような状況です。

答えて

1

インデックス関数は、2D配列がrow-major orderであることを前提としています。

offset = (y * xw) + x; 

多分列優先順位です。

+0

メモリ内の配列のレイアウトは、C言語で完全に指定されています。実装が変わる余地はありません。 –

+0

いいえ、私は行の主要な順序でそれらを置くものです。そして、私が言ったように、この例は与えられたとおりに働きます。オフセット計算が間違っていればそれはできません。合意? – fyngyrz

+0

@fyngyrz、同意しない。単純なコピーの場合(または単一のピクセル(配列要素)でしか動作しない場合)には、オフセットを生成している間は、それらを反復する順序は関係ありません。しかし、それについてもっと考えてみると、行優先と列主秩序が問題であったとしたら、2回目の修正( 'foo [offset - 1]')が有効であったはずです。 – rlibby

関連する問題