4

デコードしようとしているプログラムがあります。これは別の言語 (名前はここでは語られていません) から C に翻訳されており、それがどのように機能するかを理解したいので、ゆっくりとコードを書き直し、C が提供する優れた論理構造をすべて使用するように単純化しています。

Xと のさまざまな値を使用して、次の小さなコードがコードに表示され続けますY

ptr[X]--;
while(ptr[X])
  {
    ptr[X]--;
    ptr += Y;
  }

ptrは typechar *であり、配列はループにかなり深く埋め込まれており、入力と出力に依存しているため、どの時点でも配列の状態について実際に推測することはできません。それを次のように「単純化」できます。

for(ptr[X]--; ptr[X]; ptr[X]--, ptr += Y);

しかし、それはただひどいです。わずかに優れているのは次のとおりです。

for(ptr[X]--; ptr[X]; ptr += Y) ptr[X]--;

誰かが上記のコードをより単純化できるかどうか知りたいのですが、大歓迎です。これは 5 つ以上の場所で発生し、フロー制御を単純化して理解する能力を損なっています。そのため、誰かがより簡潔で読みやすいバージョンを提供できれば、それは素晴らしいことです。私は基本的にそれが何をするかを理解していますが、誰かがそのコードに何らかの素晴らしい洞察を提供できるなら、それも素晴らしいでしょう.

X特定のand/orのコードへの洞察Yも役立ちます。Y-2 から 2 の間になる傾向があり、X通常は 1 です。

4

4 に答える 4

8

ptr[X]は と同等な*(ptr + X)ので、次のように書き換えることができます。

for((*(ptr + X))--; *(ptr + X); (*(ptr + X))--, ptr += Y);

ここには多くの冗長性があるため、これを次のように単純化できます。

char *ptr_plus_x = ptr + X;
for((*ptr_plus_x)--; *ptr_plus_x; (*ptr_plus_x)--, ptr_plus_x += Y);

ptr_plus_x次に、完全に取り除くことができます。

ptr += X;
for((*ptr)--; *ptr; (*ptr)--, ptr += Y);

英語では、オフセット X、X+Y、X+2Y、X+3Y、... のメモリ ロケーションにアクセスし、0 のメモリ ロケーションが見つかるまで各メモリ ロケーションをデクリメントします。ただし、0 のテストは常に行われます。デクリメントの後に発生するため、実際にはそのシーケンスで値が 1 の最初のメモリ位置を探しています。それが見つかったら、それを 0 にデクリメントして終了します。

Y が 1 の場合、最初の 1 まで、連続するメモリ位置の文字列をデク​​リメントします。Y が -1 の場合、同じことが起こりますが、オフセット X から逆方向に検索します。Y が 0 の場合、無限ループが発生します。Y がその他の値の場合、検索パターンはさまざまなエントリをスキップします。

あまり直感的な機能ではないので、混乱している理由がわかります。

于 2009-05-12T03:56:59.410 に答える
3

私はスローします:

ptr[X]--
while (ptr[X]--) ptr+=Y;

最初に評価し、次にデクリメントします (while 条件の場合)。

編集:わかりました、朝は自分が嫌いです。後藤さんはこのレベルで大丈夫ですよね?

dec:  ptr[x]--
      while (ptr[X]){
           ptr+=Y;
           goto dec;
      }

(私は正直にこれを残すかどうかわからない。)

EDIT2:では、これはどうですか?(tcc は文句を言いませんでした)

 while (ptr[X]--?ptr[X]--,ptr+=Y:0){} 

編集 2 1/2;

  //longshot
  while (ptr[X]--?ptr[X]--,ptr+=Y, ptr[X]:0){} 

他のすべてが失敗した場合..

EDIT3: 今夜の最後の 1 つ。

while (ptr[X]--?ptr[X]--,ptr+=Y:0){
      if (!ptr[X]) break;
 }//good luck with this, it has been very amusing.
于 2009-05-12T03:31:06.597 に答える
2

it-which-shall-not-be-named の Web サイトには、次のように記載されています。

The semantics of the it-which-shall-not-be-named states commands can also
be succinctly expressed in terms of C, as follows (assuming that p has 
been previously defined as a char*):

>   becomes     ++p;
<   becomes     --p;
+   becomes     ++*p;
-   becomes     --*p;
.   becomes     putchar(*p);
,   becomes     *p = getchar();
[   becomes     while (*p) {
]   becomes     }

したがって、C に変換するのはかなり簡単なはずです。

編集: これは、C++ に変換された Hello World BF です。

于 2009-05-12T04:32:40.397 に答える
0

それはすでに非常に単純です。ステートメントを少なくしようとする代わりに、意図を把握してコメントを追加したいと思います。

スニペットの「a」の意味の例: Y 列の行列の列 (X) のすべての要素を減らします。たとえば、直接代入されていない言語で、+ の縦線を描画するために必要です。

インデックスを直接表示することで、この意味を明確にすることができます。

// set elements of column to cGoal
for( int decrementsToGoal = cGoal; decrementsToGoal != 0; --decrementsToGoal ) {
    // decrease all elements of column X
    for( int row = cMaxRows; M[ row*matrixsizeY + columnX ]; --row ) {
        --M[ row*matrixsizeY + columnX ];
    }
}

幸運を :)

于 2009-05-12T04:24:03.593 に答える