10

問題は、コードが何をするのか、関数が何をするのかを説明することです。

次のコードは、2年目のCおよびC++モジュールの過去の試験問題の一部です。タスクは、次のコードが何をするかを説明することです。私は提示されたとおりにコードを記述しましたが、いくつかのコメントを自分で追加しました。

int g(int * y, unsigned size, int z) {
    int tmp = y[0];
    // what type is unsigned size? Int I presume. Why would you add an int to an array of ints?
    int * b = y + size; 
    y[0] = z;
    // I have the most difficulty understanding the following.
    while (1) if (*(--b)==z){y[0] = tmp; return b - y;};
    // are the following 3 lines ever even reached?
    y[0] = tmp;
    if (tmp == z) return 0;
    else return -1;
}
4

3 に答える 3

10
// what type is unsigned size?

unsigned int呼ばれsizeます。通常のポインタ演算と同様に、ポインタに追加します。このポインタを配列の最後まで進めます。

while (1) if (*(--b)==z){y[0] = tmp; return b - y;};

OK、

  • while(1)= while(true)、または'無限ループ'
  • *(--b)bをプリデクリメントし、配列のそのインデックスから値を読み取ります
  • zが見つかった場合は、最初の要素をそこから読み取った値に置き換えて、b-y現在の配列インデックスのポインター演算を返します。

つまり、配列を逆方向にスキャンして、の最後のインスタンスを見つけ、zそれを見つけたインデックスを返します。z最初の要素として配列に配置するため、常に配列内にあります。つまりz、配列にない場合は0を返します。

// are the following 3 lines ever even reached?

いいえ、そうは思いません。

于 2012-04-16T15:55:38.020 に答える
7

符号なしサイズはどのタイプですか

unsignedの略ですunsigned int

なぜintの配列にintを追加するのですか?

ポインタと配列は同じものではありません。示したコードは、配列ではなくポインターを使用しています。int * b = y + size;行の後は、が指している場所からbエントリsizeエントリをy指すポインタです。たとえば、の場合、sizeは3番目のエントリを指します。アスキーアート:2b

+---------+
| entry 0 |<--- `y` points here
| entry 1 |
| entry 2 |<--- `b` points here if `size` is `2`
| entry 3 |
| entry 4 |
+---------+

私は次のことを理解するのが最も難しいです。

while (1) if (*(--b)==z){y[0] = tmp; return b - y;};

ループは、で識別されるエントリのyのエントリから開始することによってポイントされるメモリ内のエントリを調べます。エントリがtoの場合、エントリが見つかったインデックスに設定して返します(ポインタ演算を使用して、が指している場所と先頭の間のエントリ数を返します。ポインタをデクリメントするため、ループは逆方向に動作します。メモリー。size==zy[0]tmpb - yby--b

次の3行に到達したことはありますか?

いいえ。return最初に一致するエントリが見つかったときに関数を終了します。これは最初にある可能性があります(早い段階でy[0]設定されているため)。zただし、Ted Hoffがコメントで指摘しているように、がエントリにあるy場合、ループは開始して開始(ポイントしている場所)を超えて続行します。これにより、最終的にプログラムがメモリアクセス違反で失敗する可能性があります。size0

于 2012-04-16T15:55:35.340 に答える
5

このコードが最初に行うことは、作成者が無能であることを証明することです。しかし、私はそれが課題の一部であると考えています。無能な人々によって書かれたコードを理解することです。

手始めに:

  • unsignedは有効なC++タイプであり、の短縮形ですunsigned int。ビット操作を行わない限り、一般的には避けるのが最善です。

  • コードに配列はありません。ポインタに整数を追加しています。そして不思議なことに、[]配列のインデックス付けではありませんが、とまったく同じ
    ように定義されています。(少なくとも組み込み型については。)これを説明するために、Cに関する本を見つけたいと思うかもしれません。C ++では、ポインタ演算に関するこの混乱をすべて回避するために、通常はを使用します。a[b]*(a+b)std::vector

理解しにくい部分については、まずは正気に書いてみましょう。

while ( true ) {
    -- b;
    if ( *b == z ) {
        y[0] = tmp;
        return b - y;
    }
}

問題を引き起こす唯一のことについては、returnステートメントがあります。これはポインターの減算です。この場合、yは配列の最初の要素であるため(コードの残りの部分から判断して)、がb - y 指す要素のインデックスを計算しますb

ここでのポインターの使用は、イディオムがCで遍在し、C ++のイテレーターで実行されることを除いて、純粋な難読化になります。

そして、ループの後のコードは決して実行できないというのは正しいことです。ループを離れる唯一の方法は、を使用することreturnです。

ループを作成するためのよりクリーンな方法は次のとおりです。

int i = size;
while ( i != 0 && y[i - 1] != z ) {
    -- i;
}
y[0] = tmp;
return i;
于 2012-04-16T16:16:14.347 に答える